为什么EXPECT_CALL测试在使用取消引用的指针时意外通过
Why do EXPECT_CALL tests pass unexpectedly when using a dereferenced pointer?
我刚刚开始使用GoogleTest和GoogleMock。阅读"傻瓜"文档,该示例测试依赖于Turtle
的Painter
类:
真实对象 - 海龟.h
class Turtle {
public:
virtual ~Turtle() {}
virtual void PenDown() = 0;
};
模拟对象 - 模拟.h
class MockTurtle : public Turtle {
public:
MOCK_METHOD0(PenDown, void());
};
测试中的代码 - Painter.h
class Painter {
public:
Painter(Turtle *turtle){};
};
单元测试 - test_painter.cpp
这旨在测试是否从Painter
构造函数调用 turtle.PenDown()
方法。
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
的指针,以便我可以在测试夹具中初始化它,以便其他测试可以使用它。
您不会删除指针。
并不是说忘记删除它会导致PenDown()
被推。从不调用成员。但它是将结果报告给框架的MockTurtle
析构函数。
当您泄漏它时,不会报告任何内容。该框架认为你运行了一个空测试(它空地通过),因为它没有得到任何反馈。
当turtle
是具有自动存储持续时间的对象(不是指针)时,将在范围退出时自动调用其析构函数。这就是报告错误的原因。
这只是GoogleMock使用RAII作为样板
除了@StoryTeller的出色回答外,我认为添加一些额外的背景会很有用,这样就不会有其他人被这个问题所困扰。
我正在使用 CLion 作为我的测试运行程序,由于此错误,未显示运行测试后发生的错误。从终端运行我的测试二进制文件显示它:
./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()
被调用,我将最感兴趣!
- 如何使用基类指针引用派生类成员
- 将常量指针引用绑定到非常量指针
- 如果非动态变量被指针引用,何时超出范围?
- 转换指针引用的字符串
- 指针引用的生存期(以 C++为单位)
- 从 unique_ptr::get 发送指针作为指针引用进入函数
- 指针/引用的 CLion 格式
- 使用模板专用化来比较指针引用
- 如何保存指向抽象基类的指针/引用,但在 c++ 中仍然可以复制
- C++初始化指针/引用/复制细微差别
- 用数组或指针引用函数?
- 指针范围问题和返回类中封装的指针向量内的指针引用
- 强制转换为指针引用是否会导致未定义的行为
- 访问由 void 指针引用的结构的成员
- C 为什么当先前的步骤引发异常时,std :: shared_ptr的指针引用会被破坏
- 动态指针引用数组由三元运算符返回值,但有异常
- 悬空指向 int 和 char* 常量的指针/引用
- C++ 二维数组和指针引用
- 通过使用指针/引用,在C++中使用向量加快计算速度
- C++非类型模板模板到函数指针/引用