谷歌模拟-我可以在同一模拟对象上多次调用EXPECT_CALL吗?

鲍勃

如果我EXPECT_CALL在同一个对象的同一个模拟对象上调用两次TEST_F怎么了?

期望值是否附加到了模拟对象上,还是第二次调用消除了第一次调用的效果?

我发现After子句似乎暗示允许对同一模拟+ EXPECT_CALL的多次调用。

Luantkow

是的,您可以EXPECT_CALL多次调用同一个模拟对象。只要您确保EXPECT_CALL在实际使用模拟方法之前就调用了所有方法。否则,您的测试将依赖未定义的行为。ForDummies

重要说明:gMock要求在调用模拟函数之前设置期望值,否则行为是不确定的。特别是,您不得交错EXPECT_CALL()和对模拟函数的调用。

如何处理多个电话?该文档非常简单。ForDummies

默认情况下,当调用模拟方法时,Google Mock将以与定义相反的顺序搜索期望值,并在找到与参数匹配的有效期望值时停止(您可以将其视为“较新的规则会覆盖较旧的规则。 ”)。

让我们通过检查一些示例来考虑这对gMock用户意味着什么。我假设我们有一个带有以下标头的文件:

#include <gmock/gmock.h>

using namespace ::testing;

struct SomeMock
{
    MOCK_CONST_METHOD1(foo, void(int));
};

通过EXPECT_CALL多次调用的最简单的测试示例

TEST(Examples, DifferentArgumentsGoingToBeOk)
{
    SomeMock mock;

    EXPECT_CALL(mock, foo(4)).Times(1); // exp#1
    EXPECT_CALL(mock, foo(5)).Times(1); // exp#2

    mock.foo(4); // call#1
    mock.foo(5); // call#2
}

测试直观地进行:

  • call#1与不匹配,exp#2因此exp#1尝试并匹配。
  • call#2与匹配exp#2

两次呼叫恰好匹配一次,因此被认为满足并通过了测试。

当多个EXPECT_CALL都能匹配呼叫时,棘手的部分开始让我们考虑以下示例:

TEST(Examples, TheSameArgumentsGoingToFail) // Test fails!
{
    SomeMock mock;

    EXPECT_CALL(mock, foo(4)).Times(1); //exp#1
    EXPECT_CALL(mock, foo(4)).Times(1); //exp#2

    mock.foo(4); // call#1
    mock.foo(4); // call#2
}
  • call#1匹配exp#2gMock会以最初匹配的期望值停止,它根本不会检查exp#1
  • call#2匹配exp#2再次exp#1没有机会被匹配。

结果,测试失败,因为exp#2两次匹配而不是一次,并且exp#1完全不匹配。在测试输出中打印的所有内容:

/tmp/so/main.cpp:26: Failure // exp#2
Mock function called more times than expected - returning directly.
    Function call: foo(4)
         Expected: to be called once
           Actual: called twice - over-saturated and active
/tmp/so/main.cpp:25: Failure // exp#1
Actual function call count doesn't match EXPECT_CALL(mock, foo(4))...
         Expected: to be called once
           Actual: never called - unsatisfied and active

同样重要的是,增加新的期望值不会禁用或删除旧的期望值。他们仍然能够通过您的测试!

TEST(Examples, NewExpectCallDoesNotEraseThePreviousOne) // Test fails!
{
    SomeMock mock;

    EXPECT_CALL(mock, foo(4)).Times(1); // exp#1
    EXPECT_CALL(mock, foo(4)).Times(2); // exp#2

    mock.foo(4); // call#1
    mock.foo(4); // call#2
}

无论call#1call#2比赛的exp#2结果exp#2满足了,但是由于exp#1匹配次数不够,测试将失败

如果由于某种原因需要编写类似的测试TheSameArgumentsGoingToFail,则可以使用多种技术来防止exp#2第二次匹配。请参考文档InSequence的用法RetiresOnSaturation

TEST(Examples, InSequenceExample)
{
    SomeMock mock;

    Sequence seq;

    EXPECT_CALL(mock, foo(4)).Times(1).InSequence(seq); //exp#1
    EXPECT_CALL(mock, foo(4)).Times(1).InSequence(seq); //exp#2

    mock.foo(4); // call#1
    mock.foo(4); // call#2
}

TEST(Examples, InSequenceExampleSecondApproach)
{
    SomeMock mock;

    InSequence seq;

    EXPECT_CALL(mock, foo(4)).Times(1); //exp#1
    EXPECT_CALL(mock, foo(4)).Times(1); //exp#2

    mock.foo(4); // call#1
    mock.foo(4); // call#2
}

TEST(Examples, RetiresOnSaturationExample)
{
    SomeMock mock;

    EXPECT_CALL(mock, foo(4)).Times(1); //exp#1
    EXPECT_CALL(mock, foo(4)).Times(1).RetiresOnSaturation(); //exp#2

    mock.foo(4); // call#1
    mock.foo(4); // call#2
}

TEST(Examples, AfterExample)
{
    SomeMock mock;

    auto& exp1 = EXPECT_CALL(mock, foo(4)).Times(1); //exp#1
    EXPECT_CALL(mock, foo(4)).Times(1).After(exp1); //exp#2

    mock.foo(4); // call#1
    mock.foo(4); // call#2
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

谷歌模拟EXPECT_CALL返回值

如何使用谷歌模拟模拟宏功能

谷歌模拟 - 即使函数有不同的参数,EXPECT_CALL 也会触发

如何在谷歌测试中模拟响应?

谷歌模拟类似乎没有实现

谷歌模拟 - 如何期望不使用参数集调用函数

jquery模拟谷歌地图api上的输入键

如何模拟参数请求单元测试谷歌云功能?

如何模拟谷歌番石榴缓存生成器?

谷歌模拟委托假必须复制可构造

无法安装谷歌云功能模拟器

如何使用不同的谷歌模拟运行相同的谷歌测试用例?

Mockito可以验证模拟对象上的方法调用总数吗?

谷歌模拟-怎么说“必须使用某个参数一次调用函数,但是可以使用不同的参数多次调用”?

谷歌模拟无法模拟具有模板化参数的方法

谷歌模拟!我的测试出错。on call 将默认返回 invoke

Google Test中没有模拟的EXPECT_CALL

无法在 API.AI 项目的谷歌操作上启动网络模拟器

创建可与Analytics Reporting API一起使用的模拟帐户?[谷歌分析]

使用minitest在模拟上多次调用同一方法

如何使用with-redefs模拟对同一函数的多次调用?

使用Mockito 2.7.5对同一模拟进行多次调用的ArgumentMatchers

我如何模拟从父对象返回的所有对象在同一调用上

无法使用谷歌云函数模拟器部署函数

无法在谷歌云函数模拟器中触发发布订阅功能

如何检测谷歌浏览器是否模拟了移动设备?

离子框架谷歌地图iPhone和Android模拟器无法正常工作

Android 谷歌地图适用于模拟器,但不适用于真机

java easymock:调用模拟时我可以调用另一个方法吗?