为什么EXPECT_CALL测试在使用解除引用的指针时意外通过?

时间:2017-10-19 10:32:29

标签: c++ unit-testing pointers googletest googlemock

我刚开始使用GoogleTest和GoogleMock。阅读"for dummies" documentation示例会测试一个取决于Painter的{​​{1}}类:

真实对象 - Turtle.h

Turtle

模拟对象 - mock-turtle.h

class Turtle {
public:
    virtual ~Turtle() {}
    virtual void PenDown() = 0;
};

正在测试的代码 - Painter.h

class MockTurtle : public Turtle {
public:
    MOCK_METHOD0(PenDown, void());
};

单元测试 - test_painter.cpp

这是为了测试是否从class Painter { public: Painter(Turtle *turtle){}; }; 构造函数调用turtle.PenDown()方法。

Painter

此测试正确失败,因为永远不会调用TEST(PainterTest, CanDrawSomething) { MockTurtle turtle; EXPECT_CALL(turtle, PenDown()) .Times(AtLeast(1)); Painter painter(&turtle); }

但是,如果我更改测试以使用指向PenDown()的解除引用指针,则错误地传递。

MockTurtle

为什么在使用解除引用的指针时会通过此测试?我的代码中没有任何地方TEST(PainterTest, CanDrawSomething) { MockTurtle *turtle = new MockTurtle(); EXPECT_CALL(*turtle, PenDown()) .Times(AtLeast(1)); Painter painter(turtle); } 被调用。

对于更多上下文,我想使用指向PenDown()的指针,以便我可以在测试夹具中初始化它,以便其他测试可以使用它。

2 个答案:

答案 0 :(得分:4)

你不能删除你的指针。

并不是忘记删除它会导致PenDown()被推送。该成员从未被调用过。但是MockTurtle析构函数会将结果报告给框架。

泄漏时,没有任何报告。框架认为你运行了一个空的测试(真空通过),因为它没有得到任何反馈。

turtle是一个具有自动存储持续时间的对象(不是指针)时,会在范围退出时自动调用其析构函数。这就是报告错误的原因。

这只是GoogleMock利用RAII作为样板文件。

答案 1 :(得分:2)

除了@ StoryTeller的优秀答案之外,我认为添加一些额外的背景会很有用,所以没有其他人被这个问题所困扰。

我正在使用CLion作为我的测试运行器,并且由于this bug运行测试之后发生的错误未显示。从终端运行我的测试二进制文件显示它:

./test_painter --gtest_filter=* --gtest_color=no
Running main() from gmock_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from PainterTest
[ RUN      ] PainterTest.CanDrawSomething
[       OK ] PainterTest.CanDrawSomething (0 ms)
[----------] 1 test from PainterTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[  PASSED  ] 1 test.

/Users/donturner/PCode/workspace-kinetis/blinky/tests/test_painter.cpp:13: ERROR: this mock object (used in test PainterTest.CanDrawSomething) should be deleted but never is. Its address is @0x7fc06f402720.
ERROR: 1 leaked mock object found at program exit.

所以我忘了删除我的指针。我在测试结束时添加了以下行:

delete turtle; 

嘿嘿,测试正确地失败了:

$ ./test_painter --gtest_filter=* --gtest_color=no
Running main() from gmock_main.cc
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from PainterTest
[ RUN      ] PainterTest.CanDrawSomething
/Users/donturner/PCode/workspace-kinetis/blinky/tests/test_painter.cpp:13: Failure
Actual function call count doesn't match EXPECT_CALL(*turtle, PenDown())...
         Expected: to be called at least once
           Actual: never called - unsatisfied and active
[  FAILED  ] PainterTest.CanDrawSomething (0 ms)
[----------] 1 test from PainterTest (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[  PASSED  ] 0 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] PainterTest.CanDrawSomething

 1 FAILED TEST

如果有人能告诉我为什么忘记删除指针会导致PenDown()被调用,我会最感兴趣的!