[英]Mocking the C++ Standard Library
我在 C++ 中对 class 进行单元测试,一些公共方法称为私有方法。 我知道约定是测试公共接口,但类的功能取决于这些私有方法如何依次调用其他类及其方法。 这类似于公共接口,无论私有 function 发生什么情况,它仍然符合 API。
在大多数情况下,我已经能够模拟私有 function 中调用的类来测试 API,但在少数情况下,我遇到了引用标准库但没有设法模拟它的地方。 mocking 标准库类等有什么技巧吗? 还是我应该跳过它们?
-- 此外,我无法更改源或使用 mocking 库。
为此,我建议您使用 Typemock Isolator++ API,它允许在没有任何重新定义的情况下模拟全局方法。 看,这多么容易:
FAKE_GLOBAL(fopen);
WHEN_CALLED(fopen(0,0)).Return(_anotherFile);
而且您甚至不需要更改源代码。
如果您尝试对类的私有方法进行一些白盒测试,也许您的编译器会让您绕过访问控制? GCC 至少允许-fno-access-control
,我在白盒单元测试和数据结构自省方面都非常成功地使用了它,即 hash 在unordered_{set,map}
中的冲突。
如果您真的想狡猾,跳过访问控制还可以让您直接在其他调用之间使用成员变量。
如果您真的希望模拟标准库,那么最简单(可能唯一)的方法是正确检测您的代码。 也就是说,您必须使用中间名称,而不是直接使用标头和std
命名空间。
所以发明一个命名空间,称之为mstd
。 在您的模拟模式下,这将是您的模拟命名空间。 在非模拟模式下,这将只是std
的别名。
对于 header 文件,您必须避免直接包含标准头文件,但使用 mocking 层。 因此,您可以包含<mk-map>
而不是包含<map>
map> 。 这个 header 文件将在标准库和您的版本之间做出决定。 或许是这样的:
#ifdef MOCK_MODE
#include "mock/map.hpp"
#else
#include <map>
#endif
您可以交替地为您的编译器提供不同的包含路径,该路径位于标准库之前。 但是,由于无论如何您都必须为命名空间起别名,您仍然必须修改所有代码——因此包含这些特殊标头同样容易。
这是我能看到这个工作的唯一方法。 请注意,使用 LD_PRELOAD 或任何库技术将不起作用:C++ 标准库由许多模板类和内联函数组成。 您需要在编译时立即替换它们。
真的有必要制作标准库的模型吗? 当然,标准库函数可能存在错误,但您的模型可能比实际更可能存在错误。
我会说按原样使用它们。 如果您追踪到标准库的测试失败,那么您就发现了标准库错误。 而且,至少在短期内,您可能必须找到解决此类错误的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.