2016-06-27 20 views
1

我一直試圖在最近的工作中應用TDD,偶爾在我需要考慮模擬的最佳方法時掛斷電話。我所從事的工作涉及大量的網絡請求和文件系統訪問,所以似乎無論如何都不是嘲弄。從GMOCK文檔中,我的理解是,我最好的選擇是通過「編碼到接口」或者通過模板來模擬類。除了嘲笑測試之外,還可以對接口進行編碼而無需額外使用接口?

下面是關於我的2個主要問題「編碼到一個接口」,這之後我會給例子,希望澄清什麼,我問:

  1. 當我現在有一個接口的嘲諷身邊沒有其他用途/測試,使用這種方法還有意義嗎?
  2. 所以,現在如果我繼續「編碼到接口」,我只爲模擬/測試做了。如果不是傳遞那個接口,我只是傳遞我想要模擬的(從那個接口繼承的),我仍然是「編碼到接口」嗎?我提出這個問題是因爲有時候這會讓人感覺更可讀

#1的示例代碼...

class Thing { 
    bool IsInstalled(); // multiple filesystem calls, I want to mock this method 
}; 

bool Install(vector<Thing>& thingsToInstall) // before "coding to an interface" 
bool Install(vector<unique_ptr<IInstallable>>& thingsToInstall) // after "coding to an interface" 

class Thing : public IInstallable { 
    bool IsInstalled() override; 
}; 

class IInstallable { 
    virtual bool IsInstalled() = 0; 
}; 

我感興趣的嘲諷行爲是這些「東西」 S是否安裝與否。基於此,我可能會或可能不會做一個網絡請求(我已經嘲笑)。因此,不必傳遞「Thing」對象的向量,我必須將unique_ptr向量傳遞給IInstallable(我想要模擬的行爲/接口)。這似乎很多,所以我只能測試它,甚至不重用接口。我想我想知道我的確在這裏「編碼到接口」,這就是它的方式嗎?你也可以詳細說明它何時做,並且「編碼到接口」沒有意義嗎?

#2示例代碼...

bool Install(vector<unique_ptr<IInstallable>>& thingsToInstall) // original "coding to an interface" method from above 

所以,現在我編碼到一個界面,看到我的身邊掠過唯一原因如何unique_ptrs的界面,所以我可以測試它。我有什麼理由不應該將unique_ptrs傳遞給實現IInstallable接口的「Thing」?那麼我仍然可以直接從我的模擬課程的「事情」中繼承。這也在我的代碼中感覺更具可讀性,因爲我傳遞的是一種感覺與周圍代碼(Thing)更相關的類型,而不是更通用的接口。但是,我甚至「編碼到接口」了嗎?還是我完全摧毀了「編碼到界面」的目的(除了測試)?

這是最後的方法是什麼樣子......

bool Install(vector<unique_ptr<Thing>>& thingsToInstall) // Thing still implements IInstallable, so I can mock Thing directly 

謝謝任何​​人需要閱讀這一點,並作出迴應的時候了!我非常感謝你的幫助。

+1

重新思考你的設計 - 也許封裝整個'矢量'是一種方式去?想想單元測試是一種改進設計的方法 - 不是相反的... – PiotrNycz

回答

1

我覺得你的主要問題是關於這種說法:

好像很多,這樣我只能測試它,甚至不重用接口。

但是您的coding to interface示例似乎不適用。定義一個接口真的需要仔細的設計,而不是「我想嘲笑它,所以它應該是一個接口」。

所以回到你的榜樣,你真的應該考慮的是什麼,什麼是class Thing通用接口,是的,它應該有bool IsInstalled();,但還有什麼?

比方說,你的真實class Thing已經做法二功能,那麼你要這樣定義你的接口:

class IThing { 
    virtual bool IsInstalled() = 0; 
    virtual void DoSomething() = 0; 
}; 

然後你就可以實現它:

class Thing : public IThing{ 
    bool IsInstalled() override; 
    void DoSomething() override; 
}; 

而且使用它是這樣的:

bool Install(vector<unique_ptr<IThing>>& thingsToInstall); 

現在你有機會:

  1. 在您的函數中使用IThing;
  2. 創建Thing並將IThing傳遞給生產代碼中的函數;
  3. 創建MockIThing並將IThing傳遞給測試代碼中的函數。
+0

感謝您花時間閱讀我的文章並回復!我的IInstallable確實有另外一種方法,然後有一些變量。我試圖讓它更像一個可以「安裝」的東西的通用接口。 因此,在你的例子中,IThing是不是對Thing(它是可安裝的)進行過於具體的描述,從而破壞了「編碼到接口」的目的?當我想到界面時,我想IAnimal&Cat/Dog。我想你會如何描述IThing的目的,因爲它只能用於嘲笑?我想它也能以某種方式分離事情......你能詳細說明一下嗎? –

+0

再次感謝您花時間閱讀我的文字牆並回應!在我最後的迴應中,我的角色用完了,所以不得不縮短事情的開始。 –

+0

詳細說明「當我想到一個接口時」的意思......它只是一種常見的東西,它會在所有的動物如狗,貓和魚之間共享。 當你使IThing如此具體和更少時,這是一個通用接口,我明確計劃重複使用多個事物。它的更多我只是傳遞接口到我的東西,所以我可以測試它,而不是一些可能使用多態的通用接口(在生產中)。我想我想知道,這是可以接受的,我仍然是「編碼到接口」,並且你能描述一下它在那個時候完成了什麼嗎? –