2017-10-19 98 views
2

我剛開始使用GoogleTest和GoogleMock。讀"for dummies" documentation的示例測試一個Painter類取決於一個Turtle上:爲什麼使用取消引用的指針時,EXPECT_CALL測試意外通過?

實物 - Turtle.h

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

模仿對象 - 模擬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,以便我可以在測試夾具中初始化它,以便其他測試可以使用它。

+0

我正在使用Google Test的最新版本,並且按預期工作。嘗試使用Google Test的最新版本 – Asesh

+0

我也在使用最新版本的Google Test(從github取得)。你在做什麼特別的東西來構建你的測試可執行程我的構建命令是:'g ++ -I googlemock/include -I googletest/include -I ../source -L googlemock -lgmock_main test_painter.cpp -o test_painter' – donturner

+0

沒什麼特別的,但我使用Visual C++,這裏兩個測試都失敗 – Asesh

回答

4

你不會刪除你的指針。

並不是忘記刪除它會導致PenDown()被推送。該成員從未被調用。但是它將結果報告給框架的析構函數MockTurtle

當你泄漏它時,沒有報告。框架認爲你運行了一個空測試(真空通過),因爲它沒有得到任何反饋。

turtle是一個具有自動存儲持續時間的對象(不是指針)時,其析構函數在範圍exit處自動調用。這就是報告錯誤的原因。

這只是GoogleMock利用RAII作爲樣板。

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()被稱爲我會最感興趣的!

+0

雅,現在我可以複製這個問題。聽起來很有趣 – Asesh