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

Why do EXPECT_CALL tests pass unexpectedly when using a dereferenced pointer?

我刚刚开始使用 GoogleTest 和 GoogleMock。读取 "for dummies" documentation 示例测试 Painter class 取决于 Turtle

实物 - Turtle.h

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

模拟对象 - mock-turtle.h

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

被测代码 - Painter.h

class Painter {
public:
    Painter(Turtle *turtle){};
};

单元测试 - test_painter.cpp

这是为了测试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() 在我的代码中没有任何地方被调用。

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

除了@StoryTeller 的出色回答之外,我认为添加一些额外的背景信息会很有用,因此没有其他人会被这个问题所困扰。

我正在使用 CLion 作为我的测试 运行ner 并且由于 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() 被调用,我将非常感兴趣!

你没有删除指针。

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

当你泄漏它时,没有任何报告。该框架认为您 运行 是一个空测试(空洞地通过),因为它没有得到任何反馈。

turtle 是一个对象(不是指针)时,它具有自动存储持续时间,它的析构函数在作用域退出时被自动调用。所以才报错。

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