【问题标题】:How can I tell GoogleMock to stop checking an expectation after the test finished?我如何告诉 GoogleMock 在测试完成后停止检查期望?
【发布时间】:2015-10-14 12:56:56
【问题描述】:

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

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):错误:模拟函数调用的次数比预期的多 - 直接返回。 函数调用:Foo(0068F65C) 预期:被调用一次 实际:调用两次 - 过饱和和活跃

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

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

意外的模拟函数调用 - 直接返回。 函数调用:Foo(005AF65C) Google Mock 尝试了以下 1 个期望,但不匹配: mytest.cpp(42): EXPECT_CALL(first, Foo(_))... 预期:预期是活跃的 实际:已退役 预期:被调用一次 实际:调用一次 - 饱和并退休

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

【问题讨论】:

  • `SubscribeToFooCallsGlobal(first);` - 您可能必须在每个 TC 结束时取消订阅。
  • @PiotrNycz 当然,但这是一种解决方法。为什么 GoogleMock 测试运行后仍然检查调用?
  • 因为全局变量是全局变量。因此(那些全局变量)在 a*s 中很痛苦 - 没有人也没有任何东西(包括 gtest)可以正确处理全局变量
  • @PiotrNycz 我的观点是:为什么 GoogleMock 在测试用例运行后不清除预期?我怎样才能把它们说清楚?对我来说,在测试用例完成运行后将它们保留在适当的位置是没有意义的。
  • 您的模拟仍然存在(由您的全局成员保存为std::shared_ptr) - 那么,根据您的说法,gmock 将如何识别他们不应参与下一次测试?我的意思是他们被订阅了——所以他们被调用了——但他们预计只会被调用一次

标签: c++ unit-testing googletest googlemock


【解决方案1】:

您可以阅读documentation of Mock 几乎字面上描述您的情况:

强制验证

当它被破坏时,你友好的模拟对象会自动 验证对它的所有期望都已得到满足,并将 如果不是,则生成 Google 测试失败。这很方便,因为它离开 让您少担心一件事。也就是说,除非你不是 确定你的模拟对象是否会被破坏。

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

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

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

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

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

编辑:修复了googlemock link

【讨论】:

  • 您也可以创建Test Fixture 类,并将这个额外的代码放到它的TearDown 方法中。每次测试后都会调用此方法。您还可以添加 SetUp 方法,该方法在每次测试之前调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多