陈硕 (giantchen_AT_gmail)
Blog.youkuaiyun.com/Solstice
陈硕关于 C++ 工程实践的系列文章: http://blog.youkuaiyun.com/Solstice/category/802325.aspx
陈硕博客文章合集下载: http://blog.youkuaiyun.com/Solstice/archive/2011/02/24/6206154.aspx
本作品采用“Creative Commons 署名-非商业性使用-禁止演绎 3.0 Unported 许可协议(cc by-nc-nd)”进行许可。http://creativecommons.org/licenses/by-nc-nd/3.0/
摘要:本文讨论了在编写单元测试时 mock 系统调用(以及其他第三方库)的几种做法。
本文只考虑 Linux x86/amd64 平台。
陈硕在《分布式程序的自动化回归测试》 http://blog.youkuaiyun.com/Solstice/archive/2011/04/25/6359748.aspx 一文中曾经谈到单元测试在分布式程序开发中的优缺点(好吧,主要是缺点)。但是,在某些情况下,单元测试是很有必要的,在测试 failure 场景的时候尤显重要,比如:
- 在开发存储系统时,模拟 read(2)/write(2) 返回 EIO 错误(有可能是磁盘写满了,有可能是磁盘出坏道读不出数据)。
- 在开发网络库的时候,模拟 write(2) 返回 EPIPE 错误(对方意外断开连接)。
- 在开发网络库的时候,模拟自连接 (self-connection),网络库应该用 getsockname(2) 和 getpeername(2) 判断是否是自连接,然后断开之。
- 在开发网络库的时候,模拟本地 ephemeral port 用完,connect(2) 返回 EAGAIN 临时错误。
- 让 gethostbyname(2) 返回我们预设的值,防止单元测试给公司的 DNS server 带来太大压力。
这些 test case 恐怕很难用前文提到的 test harness 来测试,该单元测试上场了。现在的问题是,如何 mock 这些系统函数?或者换句话说,如何把对系统函数的依赖注入到被测程序中?
系统函数的依赖注入
在Michael Feathers 的《修改代码的艺术 / Working Effectively with Legacy Code》一书第 4.3.2 节中,作者介绍了链接期接缝(link seam),正好可以解决我们的问题。另外&#x