如何在测试结束后告诉GoogleMock停止检查期望?

时间:2015-10-14 12:56:57

标签: c++ unit-testing googletest googlemock

我有两个单元测试共享一些状态(不幸的是我无法改变这一点,因为重点是测试处理这个状态)。

TEST(MySuite, test1)
{
    shared_ptr<MockObject> first(make_shared<MockObject>());
    SubscribeToFooCallsGlobal(first);
    EXPECT_CALL(*first, Foo(_));//.RetiresOnSaturation();
    TriggerFooCalls(); // will call Foo in all subscribed
}

TEST(MySuite, test2)
{
    shared_ptr<MockObject> second(make_shared<MockObject>());
    SubscribeToFooCallsGlobal(second);
    EXPECT_CALL(*second, Foo(_)).Times(1);
    TriggerFooCalls(); // will call Foo in all subscribed
}

如果我单独运行测试,两者都是成功的。如果我在test1,test2的命令中运行它们,我将在 test2 中收到以下错误:

mytest.cpp(42): error: Mock function called more times than expected - returning directly.
    Function call: Foo(0068F65C)
         Expected: to be called once
           Actual: called twice - over-saturated and active

失败的期望是test1中的期望。电话确实发生了,但我想在test1完成后告诉GoogleMock 不在乎(事实上,我只想在测试运行时检查测试中的期望)

我的印象是RetiresOnSaturation会这样做,但我得到了:

Unexpected mock function call - returning directly.
    Function call: Foo(005AF65C)
Google Mock tried the following 1 expectation, but it didn't match:

mytest.cpp(42): EXPECT_CALL(first, Foo(_))...
         Expected: the expectation is active
           Actual: it is retired
         Expected: to be called once
           Actual: called once - saturated and retired

我不得不承认,让我感到困惑。这是什么意思?我该如何解决这个问题?

1 个答案:

答案 0 :(得分:6)

你可以阅读documentation of Mock几乎完全描述过你的案例:

  

强制验证

     

当它被驱逐时,您的友好模拟对象将自动进行   验证对它的所有期望是否已经满足,并且会   如果没有,则生成Google测试失败。离开时很方便   你少担心一件事。也就是说,除非你不是   确定你的模拟物体是否会被摧毁。

     

你的模拟对象最终不会被销毁怎么可能?   好吧,它可能是在堆上创建的,并且由您所拥有的代码拥有   测试。假设该代码中存在错误,并且不会删除该代码   模拟对象正确 - 你最终可能会通过测试   实际上有一个错误。

所以你不能指望,在测试案例结束时,以某种神奇的方式期望将被“停用”。如上所述 - 模拟析构函数是验证点。

在你的情况下 - 你的模拟不是局部变量 - 它们是在动态内存中创建的(引用文档中的堆)并通过SubscribeToFooCallsGlobal()保存在测试代码中,所以确保在一次测试中创建的模拟仍然存在在下一次测试中。

简单而恰当的解决方案是在每个TC结束时取消订阅 - 我不知道你是否有UnsubscribeToFooCallsGlobal() - 如果没有 - 创建这样的功能。为了确保它始终被调用 - 使用ScopeGuard pattern

有一个功能可以手动强制执行验证Mock::VerifyAndClearExpectations(&mock_object) - 但只有在您不需要在测试用例的最后一行中进行此验证时才使用它,因为这应该是破坏点。