標籤:

關於googletest裡面的一個小問題,求高手解決?

  1. using ::testing::Return;
  2. using ::testing::Sequence;
  3. int main(int argc, char **argv) {
  4. ::testing::InitGoogleMock(argc, argv);
  5. Sequence s1, s2;
  6. MockFoo mockFoo;
  7. EXPECT_CALL(mockFoo, getSize()).InSequence(s1, s2).WillOnce(Return(1));
  8. EXPECT_CALL(mockFoo, getValue()).InSequence(s1).WillOnce(Return(
  9. string("Hello World!")));
  10. cout &<&< "First: " &<&< mockFoo.getSize() &<&< endl;
  11. cout &<&< "Second: " &<&< mockFoo.getValue() &<&< endl;
  12. return EXIT_SUCCESS;
  13. }
  • 首先在第8行建立兩個序列:s1、s2。
  • 然後在第11行中,EXPECT_CALL(mockFoo, getSize()).InSequence(s1, s2)說明getSize()的行為優先於s1、s2.
  • 而第12行時,EXPECT_CALL(mockFoo, getValue()).InSequence(s1)說明getValue()的行為在序列s1中。

問題 沒有明白上述所描述的InSequence 表示方法,即為什麼說InSequence(s1, s2)說明getSize()的行為優先於s1、s2. 而 InSequence(s1)說明getValue()的行為在序列s1中呢。


我想題主是看了一篇比較不通順的翻譯。讓我們拋開翻譯,從單元測試的需求上想一想GoogleMock為什麼會設計出一個InSequence,它是為了解決一個什麼樣的問題,這樣你就很容易理解這段代碼了。

在單元測試中使用mock時,有時我們不僅想檢測『這些事兒都做了』,還想檢測『這些事兒按照一定的順序做了』。原子需求就是希望A,B按照『先A再B』的順序發生,那麼在GoogleMock里:

InSequence dummy;
EXPECT_CALL(_, A())...;
EXPECT_CALL(_, B())...;

InSequence就像一條鏈。由於構造了一個InSequence,在它的生命周期里的所有EXPECT_CALL默認都會按順序被添加進這個InSequence,以這樣的一種形式來把期望執行的順序傳達給GoogleMock。

但是實際上,『順序』不總是一條鏈那麼簡單。『先A再B』這個原子需求本質上就是圖論里的一條有向邊,所以我們實際上是在構建一張圖(Graph)。由於循環依賴在邏輯上不成立,我們的需求事實上是一張有向無環圖(DAG)。例如我們希望B1、B2都要在A之後發生,C要在B1、B2都發生了之後才發生,但是本身B1、B2兩者之間的先後順序我們卻不關心。這樣就形成了一個菱形結構。

那麼怎樣把一張DAG『講』給GoogleMock聽呢?如果說一個InSequence定義了一條鏈,那我們只要兩條鏈就能把這個概念表達清楚:

InSequence s1, s2;
EXPECT_CALL(_, A()).InSequence(s1, s2)...;
EXPECT_CALL(_, B1()).InSequence(s1 )...;
EXPECT_CALL(_, B2()).InSequence( s2)...;
EXPECT_CALL(_, C()).InSequence(s1, s2)...;

如果需求再複雜一點也沒關係。想把一個DAG表達清楚,只要把它拆成若干條鏈即可。只要每一條鏈都跟別的鏈有至少一個公共點,GoogleMock就有充足的信息來還原這個DAG。這樣一來,InSequence是不是就很好理解了?


推薦閱讀:

發現很多外掛和木馬編寫都是用MFC,MFC有必要學嗎?
如何提高C++編程能力,以及為將來找工作做準備?
为什么ASCII被摆放成现在这个样子?——我指的是各个ASCII字符的编号顺序
有什麼很好的軟體是用 Qt 編寫的?
C++不用工具,如何檢測內存泄漏?

TAG:軟體測試 | C |