【问题标题】:Mocking the C++ Standard Library模拟 C++ 标准库
【发布时间】:2011-09-30 02:21:41
【问题描述】:

我正在对 C++ 中的一个类进行单元测试,并且一些公共方法称为私有方法。我知道约定是测试公共接口,但类的功能取决于这些私有方法如何依次调用其他类及其方法。这类似于公共接口,无论私有函数发生什么,它仍然符合 API。

我已经能够模拟私有函数中调用的类来测试 API,但在少数情况下,我遇到了引用标准库但无法模拟的地方它。模拟标准库类等有什么技巧吗?还是我应该跳过它们?

-- 此外,我无法更改源代码或使用模拟库。

【问题讨论】:

  • 接骨木浆果的标准气味......
  • 需要模拟 STL 并不常见。为什么你认为你需要这样做?

标签: c++ unit-testing mocking standard-library c++-standard-library


【解决方案1】:

为此,我建议您使用Typemock Isolator++ API,它允许在不重新定义的情况下模拟全局方法。 看,这多么容易:

FAKE_GLOBAL(fopen);
WHEN_CALLED(fopen(0,0)).Return(_anotherFile);

而且您甚至不需要更改源代码。

【讨论】:

    【解决方案2】:

    如果您真的希望模拟标准库,那么最简单(可能唯一)的方法是正确检测您的代码。也就是说,您必须使用中间名称,而不是直接使用标头和 std 命名空间。

    所以发明一个命名空间,叫它mstd。在您的模拟模式下,这将是您的模拟命名空间。在非模拟模式下,这只是std 的别名。

    对于头文件,您必须避免直接包含标准头文件,而是使用模拟层。因此,您可以包括<mk-map>,而不是包括<map>。然后,此头文件将在标准库和您的版本之间做出决定。可能是这样的:

    #ifdef MOCK_MODE
        #include "mock/map.hpp"
    #else
        #include <map>
    #endif
    

    您可以交替地为您的编译器提供不同的包含路径,该路径位于标准库之前。但是,由于无论如何您都必须给命名空间起别名,所以您仍然需要修改所有代码——因此包含这些特殊标头同样容易。

    这是我可以看到它工作的唯一方法。请注意,使用 LD_PRELOAD 或任何库技术都不起作用:C++ 标准库由许多模板类和内联函数组成。您需要在编译时立即替换它们。

    【讨论】:

      【解决方案3】:

      如果您尝试对类的私有方法进行一些白盒测试,也许您的编译器会让您绕过访问控制? GCC 至少允许-fno-access-control,我在白盒单元测试和数据结构自省(即unordered_{set,map} 中的哈希冲突)中都非常成功地使用了它。

      如果您真的想要狡猾,跳过访问控制还可以让您直接在其他调用之间处理成员变量。

      【讨论】:

      • 如果您正在进行白盒测试(在这种情况下),那么所有的赌注都没有了。我只是在我的测试代码中#define private public,虽然它让我的皮肤爬行。同样,尽管您永远不应该在主线代码中这样做,但您可以将内容注入std 命名空间。我发现自己不得不这样做来白盒一个伪随机数生成器,这样我才能得到可重复的种子。
      【解决方案4】:

      真的有必要制作标准库的模型吗?当然,标准库函数可能存在错误,但您的模型可能比实际更容易出现错误。

      我会说按原样使用它们。如果您追踪到标准库的测试失败,那么您就发现了标准库错误。而且,至少在短期内,您可能必须找到解决此类错误的方法。

      【讨论】:

      • 我想说潜在有用的东西不是模拟标准库错误,而是对可能的运行时场景的反应,例如完整的文件系统、内存耗尽、文件名权限问题和竞争条件等。 ..(无论如何,这更像是评论而不是潜在的答案)。
      • 如果你想模拟系统调用,你应该使用 LD_PRELOAD 和底层 glibc 调用,而不是 libstdc++ 级别的任何东西。 C++ 是处理操作系统的错误抽象级别。
      猜你喜欢
      • 1970-01-01
      • 2011-07-08
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 2011-06-16
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      相关资源
      最近更新 更多