为什么 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。
我刚刚开始使用 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。