GoogleTest 之路3-Mocking Framework

當你寫一個原型或者測試的時候,依賴整個object 是不可行和明智的。一個 mock object和 real object 有一樣的接口(因此它能夠像同一個使用),可是讓你在運行時進行指定它應該如何被使用,它應當作什麼(哪些方法應該被調用?以何種順序?多少次?用什麼參數?什麼會被返回?)java

注意:很容易弄混 fake objects 和 mock objects。實際上fakes 和 mocks意味着不一樣的事情在Test-Driven Development(TDD)社區:python

     Fake object(僞對象) 有 工做實現,可是常常採起一些捷徑(也許讓操做不昂貴),這會使它們不適合生產。內存中的文件系統就是一個例子。git

     Mocks 是有指望的預編程對象。由一些預期會被調用的 sepcification組成。程序員

若是這對你來講太抽象的話,don't worry- 你須要記住最重要的就是mock 容許你使用它與你的代碼進行交互。當你使用mocks的時候,你對於fakes和 mocks的區別就更清晰了,github

Google C++ Mocking Framework (or Google Mock for short) 是一個用來建立 mock 類庫(叫「框架」是由於這樣聽起來更cool),就像 java 的 jMock and EasyMock數據庫

使用 Google Mock 包含如下三個基本步驟:編程

1. 使用一些簡單的macros 來描述 你想mock的接口,這將擴展你的mock 類。網絡

2. 用很直觀的語法來描述一些mock對象的指望和行爲。app

3. 練習使用mock 對象的 代碼。任何 違反 expectation 的行爲一出現就會被Google Mock 捕獲。框架

Why Google Mock?

爲何使用 Google Mock

雖然Mock Object 能夠幫助你移除測試中沒必要要的依賴,並使它們快速可靠,可是在C ++中手動使用mock是很難的:

      有些人不得不實現mocks。這個工做既乏味又容易出錯。難怪有些人想要避免它。

      手動寫的mock的質量是不可靠的,沒法預測的。你可能看過一些真正拋光過的,可是你也許會看到一些被匆忙砍掉有各類零時限制的。

      你從一個mock 得到的知識不能使用到下一個mock上面。

相比之下,Java和Python程序員有一些精細的模擬框架,自動建立mock。所以,Mock是一種被證實是有效的技術,並在這些社區普遍採用的作法。擁有正確的工具絕對有所不一樣。

Google Mock旨在幫助C ++程序員。它的靈感來自jMock和EasyMock,可是設計時考慮了C ++的細節。它會幫助你的,若是你遇到如下問題:

         你被不怎麼好的設計所困擾,早知道應該作更多的原型設計的,但一切都太遲了,可是用C++進行原型設計速度會很慢。

          您的測試很慢,由於它們依賴於太多的庫或使用昂貴的資源(例如數據庫)

           你的測試是脆弱的,由於他們使用的一些資源是不可靠的(例如網絡)

           您想要測試代碼如何處理失敗(例如,文件校驗和錯誤),可是不容易去製造這麼一個失敗。

           你想確保你的當前模塊和其餘模塊的交互是正確的,可是觀察交互是很不容易的;所以你訴諸於觀察行動結束時的反作用,這是最尷尬的

           你想 mock out 你的 依賴,除了還mock尚未被實現;坦白的講,你對那些手寫的mock 不感冒

咱們鼓勵你像這樣使用Google Mock:

         一個設計工具,它可讓你早日常常嘗試你的接口設計。更多的迭代致使更好的設計!

          一個測試工具,切斷全部測試的外部依賴,探測你的模塊和其餘模塊的交互!

Getting Started

開始吧

使用Google Mock很容易! 在你的C ++源文件中,只要#include「gtest / gtest.h」和「gmock / gmock.h」,你已經準備好了。

 

A Case for Mock Turtles

讓咱們來看一個例子。假設你在開發一個圖形程序依賴一個 LOGO-like的 API 來繪圖。你該怎樣測試它作了正確的事情呢?你能夠運行它而且與一個golden screen snapshot進行比較,可是我認可:像這樣測試是昂貴的而且很脆弱(若是你要更新到一個全新抗鋸齒的圖像該怎麼辦?你要更新你全部的golden images),若是你的全部測試都是這樣的,這就很痛苦了。Fortunately,你學習到了Dependency Injection而且知道該做什麼:不要讓你的application 直接 調用 drawing API, 把API包在一個接口裏(say, Turtle) and code to that interface:

 

class Turtle {
  ...
  virtual ~Turtle() {}
  virtual void PenUp() = 0;
  virtual void PenDown() = 0;
  virtual void Forward(int distance) = 0;
  virtual void Turn(int degrees) = 0;
  virtual void GoTo(int x, int y) = 0;
  virtual int GetX() const = 0;
  virtual int GetY() const = 0;
};

(注意,Turtle的析構函數必須是虛擬的,就像你打算繼承的全部類的狀況同樣 - 不然當經過基類指針刪除一個對象時,派生類的析構函數不會被調用,你會獲得損壞的程序狀態,如內存泄漏。)

您能夠控制 使用PenUp()和PenDown()控制turtle的運動是否留下軌跡,並經過 Forward(),Turn()和GoTo()控制其運動。最後,GetX()和GetY()告訴你當前位置的turtle。

你的程序一般正常使用這個接口的實際實現。在測試中,你可使用 實現的Mock來替換。這讓你很容易的檢查你程序你調用的 drawing primitives。傳了哪些參數,以什麼樣的順序。以這種方式編寫的測試更強大,更容易讀取和維護(測試的意圖表示在代碼中,而不是在一些二進制圖像中)運行得多,快得多。

 

Writing the Mock Class

 

若是你幸運,你須要使用的mock已經被一些好的人實現。可是,你發現本身在寫一個模擬class,放鬆- Google Mock將這個任務變成一個有趣的遊戲!

How to Define It

使用Turtle接口做爲示例,如下是您須要遵循的簡單步驟:

1. MockTurtle繼承Turtle類  

2.使用Turtle的虛函數(雖然可使用模板來模擬非虛方法 mock non-virtual methods using templates,可是它更多的涉及)。計算它有多少參數。

3. 在 public 區: section of the child class, write MOCK_METHODn(); (or MOCK_CONST_METHODn(); if you are mocking a const method), where n is the number of the arguments; if you counted wrong, shame on you, and a compiler error will tell you so.

4. 如今來到有趣的部分:你採起函數簽名,剪切和粘貼函數名做爲宏的第一個參數,留下的做爲第二個參數(若是你好奇,這是類型的功能)

5. 重複,直到您要模擬的全部虛擬功能完成。

After the process, you should have something like:

#include "gmock/gmock.h"  // Brings in Google Mock.
class MockTurtle : public Turtle {
 public:
  ...
  MOCK_METHOD0(PenUp, void());
  MOCK_METHOD0(PenDown, void());
  MOCK_METHOD1(Forward, void(int distance));
  MOCK_METHOD1(Turn, void(int degrees));
  MOCK_METHOD2(GoTo, void(int x, int y));
  MOCK_CONST_METHOD0(GetX, int());
  MOCK_CONST_METHOD0(GetY, int());
};

您不須要在其餘地方定義這些模擬方法 - MOCK_METHOD *宏將爲您生成定義。 就是這麼簡單! 

一旦你掌握了它,你能夠快速的寫出 mock class,以致於你的 source control system 都不能處理你的check-in 了

Tips: 若是 這對你來講工做量太大了,你能夠在 Google Mock 的 scripts/generator/目錄下面找到gmock_gen.py 工具。

Command-line 工具須要python2.4 安裝。你只要給它一個 定義了抽象類的C++文件,它就會給你打印 其mock class。因爲C++語言的複雜性,這個腳本可能不老是工做正常,但確實頗有用,read the user documentation.

Where to Put It

當你定義了 mock class,你得決定你把這些定義放到什麼地方。有些人把它放在一個* _test.cc。當這些 mock對象是被一我的或者一個團隊使用的時候,這樣定義就很好。不然,當Foo的全部者改變它,你的測試可能會中斷。 (你不能真正指望Foo的維護者修復使用Foo的每一個測試,你能嗎?)

因此,經驗法則是:若是你須要模擬Foo而且它由其餘人擁有,在Foo的包中定義模擬類(更好的是,在一個測試子包中,你能夠清楚地分離生產代碼和測試實用程序),而且把它放在mock_foo.h。而後每一個人均可以從它們的測試引用mock_foo.h。若是Foo變化,只有一個MockFoo的副本要更改,只有依賴於更改的方法的測試須要修復。

另一種方法:你能夠在Foo的頂部引入一個 薄層FooAdaptor ,並將代碼引入這一新的接口。由於你擁有FooAdaptor,你能夠更容易的吸取Foo的變化。雖然這是最初的工做,仔細選擇適配器接口可使您的代碼更容易編寫和更加可讀性,由於你能夠選擇FooAdaptor適合你的特定領域比Foo更好。

 

Using Mocks in Tests

一旦你有了Mock 類,使用它很是容易。典型的工做流程以下:

1. 從測試命名空間導入Google Mock名稱,以便您可使用它們(每一個文件只需執行一次。請記住,命名空間是一個好主意,有利於您的健康。)

2. 建立一些 mock對象

3.指定你對它們的指望(一個方法被調用多少次?有什麼參數?它應該作什麼等等)。

4.練習一些使用mock的代碼; 可使用Google Test斷言檢查結果。若是一個mock方法被調用超過預期或錯誤的參數,你會當即獲得一個錯誤。

5. 當模mock destructed,Google Mock將自動檢查是否知足了對其的全部指望

例子:

#include "path/to/mock-turtle.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
using ::testing::AtLeast;                     // #1

TEST(PainterTest, CanDrawSomething) {
  MockTurtle turtle;                          // #2
  EXPECT_CALL(turtle, PenDown())              // #3
      .Times(AtLeast(1));

  Painter painter(&turtle);                   // #4

  EXPECT_TRUE(painter.DrawCircle(0, 0, 10));
}                                             // #5

int main(int argc, char** argv) {
  // The following line must be executed to initialize Google Mock
  // (and Google Test) before running the tests.
  ::testing::InitGoogleMock(&argc, argv);
  return RUN_ALL_TESTS();
}

正如你可能已經猜到的,這個測試檢查PenDown()被調用至少一次。 若是painter對象沒有調用此方法,您的測試將失敗,並顯示以下消息:

path/to/my_test.cc:119: Failure
Actual function call count doesn't match this expectation:
Actually: never called;
Expected: called at least once.

提示1:若是從Emacs緩衝區運行測試,您能夠在錯誤消息中顯示的行號上按<Enter>,直接跳到失敗的預期。

提示2:若是你的mock object 歷來沒有被刪除,最終的驗證不會發生。所以,當您在堆上分配mock時,在測試中使用堆泄漏檢查器是個好主意。

重要提示:Google Mock 須要expectation 在mock 函數被調用以前就設置,否者 行爲就是 未定義的(undefined)。尤爲是,你不能交錯 EXPECT_CALL()和調用函數

這意味着EXPECT_CALL()應該被讀取爲指望call將在將來發生,而不是call已經發生。爲何Google Mock會這樣工做?

好的,事先指按期望容許Google Mock在上下文(堆棧跟蹤等)仍然可用時當即報告違例。這使得調試更容易。

誠然,這個測試是設計的,沒有作太多。不使用Google Mock,您也能夠輕鬆實現相同的效果。然而,正如咱們將很快揭示的,Google Mock容許你作更多的。

Using Google Mock with Any Testing Framework

若是您要使用除Google測試(例如CppUnit或CxxTest)以外的其餘測試框架做爲測試框架,只需將上一節中的main()函數更改成:

int main(int argc, char** argv) {
  // The following line causes Google Mock to throw an exception on failure,
  // which will be interpreted by your testing framework as a test failure.
  ::testing::GTEST_FLAG(throw_on_failure) = true;
  ::testing::InitGoogleMock(&argc, argv);
  ... whatever your testing framework requires ...
}

這種方法有一個catch:它有時使Google Mock從一個模擬對象的析構器中拋出異常。對於某些編譯器,這有時會致使測試程序崩潰。 你仍然能夠注意到測試失敗了,但它不是一個優雅的失敗。

更好的解決方案是使用Google Test的事件偵聽器APIevent listener API 來正確地向測試框架報告測試失敗。 您須要實現事件偵聽器接口的OnTestPartResult()方法,但它應該是直接的。

若是這證實是太多的工做,咱們建議您堅持使用Google測試,它與Google Mock無縫地工做(實際上,它在技術上是Google Mock的一部分)。 若是您有某個緣由沒法使用Google測試,請告訴咱們。

Setting Expectations

成功使用Mock Object的關鍵是對它設置正確的指望。 若是你設置的指望太嚴格,你的測試將失敗做爲無關的更改的結果。 若是你把它們設置得太鬆,錯誤能夠經過。 你想作的只是正確的,使你的測試能夠捕獲到你想要捕獲的那種錯誤。 Google Mock爲您提供了必要的方法「恰到好處」。

General Syntax

在 Google Mock 中咱們在 mock mecthod 中使用 EXPECT_CALL() 宏去設置expectation。 通常的語法是:

EXPECT_CALL(mock_object, method(matchers))
    .Times(cardinality)
    .WillOnce(action)
    .WillRepeatedly(action);

宏有兩個參數:首先是mock對象,而後是方法及其參數。 請注意,二者之間用逗號(,)分隔,而不是句點(.)。 (爲何要使用逗號?答案是,這是必要的技術緣由。)

宏以後能夠是一些可選的子句,提供有關指望的更多信息。 咱們將在下面的章節中討論每一個子句是如何工做的。

此語法旨在使指望讀取如英語。 例如,你可能猜到

using ::testing::Return;
...
EXPECT_CALL(turtle, GetX())
    .Times(5)
    .WillOnce(Return(100))
    .WillOnce(Return(150))
    .WillRepeatedly(Return(200));

 turtle對象的GetX()方法將被調用五次,它將第一次返回100,第二次返回150,而後每次返回200。 有些人喜歡將這種語法風格稱爲域特定語言(DSL)。

注意:爲何咱們使用宏來作到這一點? 它有兩個目的:第一,它使預期容易識別(經過grep或由人類讀者),其次它容許Google Mock在消息中包括失敗的指望的源文件位置,使調試更容易。

 

Matchers: What Arguments Do We Expect?

當一個mock函數接受參數時,咱們必須指定咱們指望什麼參數; 例如:

// Expects the turtle to move forward by 100 units.
EXPECT_CALL(turtle, Forward(100));

 有些時候你也許不想要太具體(記住,談論測試太僵硬,超過規範致使脆弱的測試和模糊測試的意圖,所以,咱們鼓勵你只指定必要的 -很少也很多 ),若是你只關心 Forward() 會被調用,可是對 具體的參數不感興趣,寫_ 做爲 參數,這意味「什麼均可以」:

using ::testing::_;
...
// Expects the turtle to move forward.
EXPECT_CALL(turtle, Forward(_));

_是咱們稱爲匹配器的實例.匹配器就像一個謂詞,能夠測試一個參數是不是咱們指望的.你能夠在EXPECT_CALL()裏面使用一個匹配器來替換某一個參數。內置匹配器的列表能夠在CheatSheet中找到。 例如,這裏是Ge(大於或等於)匹配器:

using ::testing::Ge;
...
EXPECT_CALL(turtle, Forward(Ge(100)));

這檢查,turtle將被告知前進至少100單位。

Cardinalities: How Many Times Will It Be Called?

咱們能夠在EXPECT_CALL()以後指定的第一個子句是Times()。咱們把它的參數稱爲基數,由於它告訴調用應該發生多少次。它容許咱們重複一個指望屢次,而不實際寫屢次。更重要的是,一個基數能夠是「模糊的」,就像一個匹配器。這容許用戶準確地表達測試的意圖。

一個有趣的特殊狀況是當咱們說Times(0)。你可能已經猜到了 - 這意味着函數不該該使用給定的參數,並且Google Mock會在函數被(錯誤地)調用時報告一個Google測試失敗。咱們已經看到AtLeast(n)做爲模糊基數的一個例子。有關您可使用的內置基數列表,請參見CheatSheet

Times()子句能夠省略。若是你省略Times(),Google Mock會推斷出你的基數。規則很容易記住:

  • 若是WillOnce()和WillRepeatedly()都不在EXPECT_CALL()中,則推斷的基數是Times(1)。
  • 若是有n個WillOnce(),但沒有WillRepeatedly(),其中n> = 1,基數是Times(n)
  • 若是有n個WillOnce()和一個WillRepeatedly(),其中n> = 0,基數是Times(AtLeast(n))。

 快速測驗:若是一個函數指望被調用兩次,但實際上調用了四次,你認爲會發生什麼?

Actions: What Should It Do?

記住,一個模擬對象實際上沒有工做實現? 咱們做爲用戶必須告訴它當一個方法被調用時該作什麼。 這在Google Mock中很容易。

首先,若是一個模擬函數的返回類型是內置類型或指針,該函數有一個默認動做(一個void函數將返回,一個bool函數將返回false,其餘函數將返回0)。

此外,在C ++ 11及以上版本中,返回類型爲默承認構造(即具備默認構造函數)的模擬函數具備返回默認構造值的默認動做。 若是你不說什麼,這個行爲將被使用。

第二,若是模擬函數沒有默認動做,或者默認動做不適合你,你可使用一系列WillOnce()子句指定每次指望匹配時要採起的動做,後跟一個可選的WillRepeatedly ()。例如:

using ::testing::Return;
...
EXPECT_CALL(turtle, GetX())
    .WillOnce(Return(100))
    .WillOnce(Return(200))
    .WillOnce(Return(300));

這說明turtle.GetX()將被調用三次(Google Mock從咱們寫的WillOnce()子句中推斷出了這一點,由於咱們沒有明確寫入Times()),而且會返回100,200, 和300。

using ::testing::Return;
...
EXPECT_CALL(turtle, GetY())
    .WillOnce(Return(100))
    .WillOnce(Return(200))
    .WillRepeatedly(Return(300));

turtle.GetY()將被調用至少兩次(Google Mock知道這一點,由於咱們寫了兩個WillOnce()子句和一個WillRepeatedly(),沒有明確的Times()),將第一次返回100,200 第二次,300從第三次開始。

固然,若是你明確寫一個Times(),Google Mock不會試圖推斷cardinality(基數)自己。 若是您指定的數字大於WillOnce()子句,該怎麼辦? 好了,畢竟WillOnce()已用完,Google Mock每次都會爲函數執行默認操做(除非你有WillRepeatedly()。)。

除了Return()以外,咱們能夠在WillOnce()中作什麼? 您可使用ReturnRef(variable)返回引用,或調用預約義函數等。

重要說明:EXPECT_CALL()語句只評估一次操做子句,即便操做可能執行屢次。 所以,您必須當心反作用。 如下可能不會作你想要的:

int n = 100;
EXPECT_CALL(turtle, GetX())
.Times(4)
.WillRepeatedly(Return(n++));

不是連續返回100,101,102,...,這個mock函數將老是返回100,由於n ++只被計算一次。 相似地,當執行EXPECT_CALL()時,Return(new Foo)將建立一個新的Foo對象,而且每次都返回相同的指針。 若是你想要每次都發生反作用,你須要定義一個自定義動做,咱們將在 CookBook中教授。

另外一個測驗! 你認爲如下是什麼意思?

using ::testing::Return;
...
EXPECT_CALL(turtle, GetY())
.Times(4)
.WillOnce(Return(100));

顯然turtle.GetY()被指望調用四次。但若是你認爲它會每次返回100,三思然後行!請記住,每次調用函數時都將使用一個WillOnce()子句,而後執行默認操做。因此正確的答案是turtle.GetY()將第一次返回100,但從第二次返回0,由於返回0是int函數的默認操做

Using Multiple Expectations

到目前爲止,咱們只列出了你有一個指望的例子。更現實地,你要指定對多個模擬方法的指望,這可能來自多個模擬對象。

默認狀況下,當調用模擬方法時,Google Mock將按照它們定義的相反順序搜索指望值,並在找到與參數匹配的活動指望時中止(您能夠將其視爲「新規則覆蓋舊的規則「)。若是匹配指望不能再接受任何調用,您將獲得一個上限違反的失敗。這裏有一個例子:

using ::testing::_;
...
EXPECT_CALL(turtle, Forward(_));  // #1
EXPECT_CALL(turtle, Forward(10))  // #2
    .Times(2);

若是Forward(10)在一行中被調用三次,第三次它將是一個錯誤,由於最後的匹配指望(#2)已經飽和。然而,若是第三個Forward(10)被Forward(20)替換,則它將是OK,由於如今#1將是匹配指望。

附註:Google Mock爲何要以與預期相反的順序搜尋匹配?緣由是,這容許用戶在模擬對象的構造函數中設置默認指望,或測試夾具的設置階段中設置默認指望,而後經過在測試體中寫入更具體的指望來定製模擬。因此,若是你對同一個方法有兩個指望,你想把一個具備更多的特定的匹配器放在另外一個以後,或更具體的規則將被更爲通常的規則所覆蓋。

Ordered vs Unordered Calls

默認狀況下,即便未知足較早的指望,指望也能夠匹配調用。換句話說,調用沒必要按照指望被指定的順序發生

有時,您可能但願全部預期的調用以嚴格的順序發生。在Google Mock中說這很容易

using ::testing::InSequence;
...
TEST(FooTest, DrawsLineSegment) {
  ...
  {
    InSequence dummy;

    EXPECT_CALL(turtle, PenDown());
    EXPECT_CALL(turtle, Forward(100));
    EXPECT_CALL(turtle, PenUp());
  }
  Foo();
}

經過建立類型爲InSequence的對象,其範圍中的全部指望都被放入序列中,而且必須按順序發生。由於咱們只是依靠這個對象的構造函數和析構函數作實際的工做,它的名字真的可有可無。

在這個例子中,咱們測試Foo()按照書寫的順序調用三個指望函數。若是調用是無序的,它將是一個錯誤。

若是你關心一些呼叫的相對順序,但不是全部的呼叫,你能指定一個任意的部分順序嗎?答案是...是的!若是你不耐煩,細節能夠在CookBook中找到。)

All Expectations Are Sticky (Unless Said Otherwise)

全部指望都是粘滯的(Sticky)(除非另有說明)

如今,讓咱們作一個快速測驗,看看你能夠多好地使用這個模擬的東西。你會如何測試,turtle被要求去原點兩次(你想忽略任何其餘指令)?

在你提出了你的答案,看看咱們的比較的筆記(本身先解決 - 不要欺騙!):

using ::testing::_;
...
EXPECT_CALL(turtle, GoTo(_, _))  // #1
    .Times(AnyNumber());
EXPECT_CALL(turtle, GoTo(0, 0))  // #2
    .Times(2);

假設turtle.GoTo(0,0)被調用了三次。 第三次,Google Mock將看到參數匹配指望#2(記住,咱們老是選擇最後一個匹配指望)。 如今,因爲咱們說應該只有兩個這樣的調用,Google Mock會當即報告錯誤。 這基本上是咱們在上面「使用多個指望」部分中告訴你的。

這個例子代表,Google Mock的指望在默認狀況下是「粘性」,即便在咱們達到其調用上界以後,它們仍然保持活動。 這是一個重要的規則要記住,由於它影響規範的意義,而且不一樣於它在許多其餘Mock框架中作的(爲何咱們這樣作?由於咱們認爲咱們的規則使常見的狀況更容易表達和 理解。)。

簡單? 讓咱們看看你是否真的理解它:下面的代碼說什麼?

using ::testing::Return;
...
for (int i = n; i > 0; i--) {
  EXPECT_CALL(turtle, GetX())
      .WillOnce(Return(10*i));
}

若是你認爲它說,turtle.GetX()將被調用n次,並將返回10,20,30,...,連續,三思然後行! 問題是,正如咱們所說,指望是粘性的。 因此,第二次turtle.GetX()被調用,最後(最新)EXPECT_CALL()語句將匹配,並將當即致使「上限超過(upper bound exceeded)」錯誤 - 這段代碼不是頗有用!

一個正確的說法是turtle.GetX()將返回10,20,30,...,是明確說,指望是不粘的。 換句話說,他們應該在飽和後儘快退休:

using ::testing::Return;
...
for (int i = n; i > 0; i--) {
  EXPECT_CALL(turtle, GetX())
    .WillOnce(Return(10*i))
    .RetiresOnSaturation();
}

並且,有一個更好的方法:在這種狀況下,咱們指望調用發生在一個特定的順序,咱們排列動做來匹配順序。 因爲順序在這裏很重要,咱們應該顯示的使用一個順序:

using ::testing::InSequence;
using ::testing::Return;
...
{
  InSequence s;

  for (int i = 1; i <= n; i++) {
    EXPECT_CALL(turtle, GetX())
        .WillOnce(Return(10*i))
        .RetiresOnSaturation();
  }
}

Uninteresting Calls

模擬對象可能有不少方法,並非全部的都是那麼有趣。例如,在一些測試中,咱們可能不關心GetX()和GetY()被調用多少次。

在Google Mock中,若是你對一個方法不感興趣,只是不要說什麼。若是調用此方法,您將在測試輸出中看到一個警告,但它不會失敗。

What Now?

恭喜!您已經學會了足夠的Google Mock開始使用它。如今,您可能想要加入googlemock討論組,而且實際上使用Google Mock編寫一些測試 - 這頗有趣。嘿,它甚至能夠上癮 - 你已經被警告。

而後,若是你想增長你的Mock商,你應該移動到 CookBook。您能夠了解Google Mock的許多高級功能,並提升您的享受和測試幸福的水平。

相關文章
相關標籤/搜索