GoogleMock:如何准确地期待一个带有特定参数的调用,并查看失败的诊断?

Posted

技术标签:

【中文标题】GoogleMock:如何准确地期待一个带有特定参数的调用,并查看失败的诊断?【英文标题】:GoogleMock: how to expect precisely one call with a certain argument, and see diagnostic on failure? 【发布时间】:2014-09-26 13:31:37 【问题描述】:

也许是一个技巧问题,我的问题是,如果我写:

EXPECT_CALL(mock, handleMessage(_)).Times(0);                           // expectation #1
EXPECT_CALL(mock, handleMessage(Pointee(IsLike(aSpecificMessage))));    // expectation #2

... 和方法 handleMessage 被调用一次,但使用不同的参数(不是 aSpecificMessage),那么失败看起来像:

Mock function called more times than expected - returning default value.
    Function call: handleMessage(0x8b5378)
          Returns: false
         Expected: to be never called
           Actual: called once - over-saturated and active

Google Mock 不会打印关于为什么参数与预期 #2 中的谓词不匹配的诊断信息。 这大概是因为期望 #1 是第一个失败的(?)。

如果我省略了期望 #1,那么失败就很冗长,大致如下:

Google Mock tried the following 1 expectation, but it didn't match:

../../test/Test.cpp:143: EXPECT_CALL(mock, handleMessage(Pointee(IsLike(aSpecificMessage))))...
  Expected arg #0: points to a value that <....>
           Actual: 0xfeaf18, which points to <.....>

我正在使用自定义匹配器IsLike,并且遇到了生成非常明确的不匹配原因的麻烦,我希望将它们打印出来。我也不想放弃期望 #1,因为它位于“默认”部分,默认情况下,我不希望在其余测试中调用该模拟。

【问题讨论】:

【参考方案1】:

看来您应该使用the StrictMock template modifier。让我们使用这个简单的类和模拟:

struct Foo

    virtual void function(int) 
    
;

struct MockFoo: public Foo

    MOCK_METHOD1(function, void(int x));
;

让我们从一个练习该方法的基本测试开始:

TEST(MockTest, basic_one_expectation)

    MockFoo foo;
    EXPECT_CALL(foo, function(4));
    Foo& foo1(foo);
    foo1.function(3);

输出:

[运行]模拟测试.basic_one_expectation 未知文件:失败 意外的模拟函数调用 - 直接返回。 函数调用:函数(3) Google Mock 尝试了以下 1 个期望,但不匹配: mock-test.cpp:298: EXPECT_CALL(foo, function(4))... 预期参数 #0:等于 4 实际:3 预期:被调用一次 实际:从未打电话 - 不满意和积极 mock-test.cpp:298:失败 实际函数调用计数与 EXPECT_CALL(foo, function(4)) 不匹配... 预期:被调用一次 实际:从未打电话 - 不满意和积极 [失败] MockTest.basic_one_expectation (1 ms)

这是您已经考虑过的替代方案之一,但您不想要它,因为您有其他测试对是否调用该函数没有任何特别的期望,并且您希望这些测试失败,如果无论如何都会调用函数。提醒一下,让我们看看当我们尝试这样的测试时发生了什么:

TEST(MockTest, basic_no_expectation)

    MockFoo foo;
    Foo& foo1(foo);
    foo1.function(3);

输出:

[运行]模拟测试.basic_no_expectation GMOCK 警告: 无趣的模拟函数调用 - 直接返回。 函数调用:函数(3) 堆栈跟踪: [确定] MockTest.basic_no_expectation (1 ms)

我们收到警告,但测试仍然通过。这对你没有好处。看看StrictMock有什么效果:

TEST(MockTest, strict_no_expectation)

    ::testing::StrictMock<MockFoo> foo;
    Foo& foo1(foo);
    foo1.function(3);

输出:

[运行] MockTest.strict_no_expectation 未知文件:失败 无趣的模拟函数调用 - 直接返回。 函数调用:函数(3) [失败] MockTest.strict_no_expectation (0 ms)

我们不必明确表示我们不希望调用该函数,但是无论如何调用该函数时,测试都会正确失败。正是你想要的。

最后,让我们看看StrictMock 在函数参数有明确期望的情况下会发生什么:

TEST(MockTest, strict_one_expectation)

    ::testing::StrictMock<MockFoo> foo;
    EXPECT_CALL(foo, function(4));
    Foo& foo1(foo);
    foo1.function(3);

输出:

[运行] MockTest.strict_one_expectation 未知文件:失败 意外的模拟函数调用 - 直接返回。 函数调用:函数(3) Google Mock 尝试了以下 1 个期望,但不匹配: mock-test.cpp:307: EXPECT_CALL(foo, function(4))... 预期参数 #0:等于 4 实际:3 预期:被调用一次 实际:从未打电话 - 不满意和积极 mock-test.cpp:307:失败 实际函数调用计数与 EXPECT_CALL(foo, function(4)) 不匹配... 预期:被调用一次 实际:从未打电话 - 不满意和积极 [失败] MockTest.strict_one_expectation (0 ms)

诊断显示参数不匹配的原因,就像上面显示的原始 basic_one_expectation 测试一样。

【讨论】:

以上是关于GoogleMock:如何准确地期待一个带有特定参数的调用,并查看失败的诊断?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 googlemock 中作为 void 指针传递的字符串参数

如何在世界地图上准确地绘制半径以公里为单位的圆

带有文本选择控件的浮动工具栏

GoogleMock 在 Linux 上不是线程安全的吗?

如何使用 Resharper 准确找出哪个规则将语法突出显示应用于 VS2022 中的特定代码元素?

在特定时间准确剪切视频而不会降低质量