c++ - 在设置阶段忽略模拟调用

标签 c++ unit-testing googletest googlemock

我经常遇到这样的问题,即在测试的“有趣”部分开始之前,模拟对象需要进入某种状态。

例如,假设我要测试以下类:

struct ToTest
{
    virtual void onEnable();
    virtual void doAction();
};

因此,我创建了以下模拟类:

struct Mock : ToTest
{
    MOCK_METHOD0(onEnable, void());
    MOCK_METHOD0(doAction, void());
};

第一个测试是 onEnable当系统使用 ToTest 时被调用启用对象:

TEST(SomeTest, OnEnable)
{
    Mock mock;
    // register mock somehow

    // interesting part of the test
    EXPECT_CALL(mock, onEnable());
    EnableSystem();
}

到目前为止,还不错。第二个测试是 doAction在系统执行操作时调用并启用。因此,应该在测试的有趣部分开始之前启用系统:

TEST(SomeTest, DoActionWhenEnabled)
{
    Mock mock;
    // register mock somehow

    // initialize system
    EnableSystem();

    // interesting part of the test
    EXPECT_CALL(mock, doAction());
    DoSomeAction();

}

这有效,但会发出一个恼人的警告,提示对 onEnable 的无趣调用.这个问题似乎有两个常见的修复方法:

  1. 使用 NiceMock<Mock>禁止所有此类警告;和
  2. 添加 EXPECT_CALL(mock, onEnable())声明。

我不想使用第一种方法,因为可能会有其他不应该发生的无趣调用。我也不喜欢第二种方法,因为我已经(在第一个测试中)测试了 onEnable当系统启用时被调用;因此,我不想在启用系统上运行的所有测试中重复这种期望。

我希望能够做到的是,到某个点为止的所有模拟调用都应该被完全忽略。在此示例中,我希望仅从“测试的有趣部分”评论开始检查期望。

有没有办法使用 Google Mock 来完成此操作?

最佳答案

烦人的是必要的函数都在那里:gmock/gmock-spec-builders.h定义了Mock::AllowUninterestingCalls等来控制警告的产生对于特定的模拟对象。使用这些函数,应该可以暂时禁用有关无趣调用的警告。

然而,问题在于这些函数是私有(private)的。好消息是 Mock 类有一些可以被滥用的模板 friend (例如,NiceMock)。所以我创建了以下解决方法:

namespace testing
{
// HACK: NiceMock<> is a friend of Mock so we specialize it here to a type that
// is never used to be able to temporarily make a mock nice. If this feature
// would just be supported, we wouldn't need this hack...
template<>
struct NiceMock<void>
{
    static void allow(const void* mock)
    {
        Mock::AllowUninterestingCalls(mock);
    }

    static void warn(const void* mock)
    {
        Mock::WarnUninterestingCalls(mock);
    }

    static void fail(const void* mock)
    {
        Mock::FailUninterestingCalls(mock);
    }
};

typedef NiceMock<void> UninterestingCalls;
}

这让我可以通过 UninterestingCalls typedef 访问私有(private)函数。

关于c++ - 在设置阶段忽略模拟调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22745349/

相关文章:

带有运算符的 std::array 的 C++11 类型别名

c++ - 函数调用后计算多维数组元素

javascript - 测试 React Js 根组件

ruby - 是否可以在不调用初始化的情况下实例化 Ruby 类?

unit-testing - HSQLDB 和 JavaDB 有什么区别?哪一种适合单元测试?

c++ - 如何使我的迭代器类看起来不像容器类?

c++ - 在 gtest 中显示失败的函数而不是宏

c++ - 将模拟对象分配给 protected 成员

c++ - 从另一个线程发出信号是否安全?

c++ - 逻辑错误,需要协助