2011-04-20 130 views
2

假設您正在測試類A並且它有dependency injectionB,它的依賴注入爲C
所以你模擬B但它的唯一構造函數需要注入C,所以你也必須模擬C以及注入模擬的C到嘲諷的B,然後注入到A
如果您有5個連續依賴關係,該怎麼辦?使用依賴注入嘲笑C++類

有什麼替代方案?

我使用Google Mock,所以具體答案也會有所幫助。

回答

-2

在這種情況下,你應該通過指針注入,而不是通過引用,那麼你可以傳遞一個NULL指針。假設你是一個對象確實是一個模擬對象而不是一個假對象,這將工作,因此它沒有真正依賴注入的對象。

對於boost::shared_ptr,你可以做到以下幾點:

boost::shared_ptr<C> null_c_ptr; 
MockB mock_b(null_c_ptr); 
+3

有趣,接受-2分:) – 2014-06-19 17:49:24

4

如果您更改設計以使類取決於接口而不是具體類,則可以擺脫構造函數問題。除了提高可測試性之外,它還可以提高可重用性和可維護性,代價是更多的代碼(接口)。

+0

你能不能解釋一下?這會消除依賴注入的必要性嗎? – Jonathan 2011-04-20 08:08:16

+0

它不會刪除依賴注入,只會注入一個接口。所以編譯時只有接口必須在範圍內。這減少了耦合,並且(在你的例子中)C不再可見,因爲你不再具體的B了。 – Emile 2011-07-08 18:20:36

6

Emile有正確的想法,你應該依賴於接口而不是具體的類。所以,在你的榜樣,將是這樣的:

#include <iostream> 
using namespace std; 

class C { 
public: 
    int x; 
}; 

class B { 
public: 
    ~B(){}; 
    virtual void doSomething() = 0; 
}; 

class ConcreteB : public B{ 
public: 
    ConcreteB(C c) : m_c(c) {} 
    void doSomething(){ 
     std::cout << "HelloWorld" << std::endl; 
    } 
private: 
    C m_c; 
}; 
class A{ 
public: 
    A(B *b): m_b(b){} 

    void functionToTestWithSideEffect(){ 
     m_b->doSomething(); 
    } 
private: 
    B *m_b; 

}; 

//#include <gmock/gmock.h> 

int main() { 
    C c; 
    c.x = 42; 
    ConcreteB b(c); 
    A a(&b); 
    a.functionToTestWithSideEffect(); 
    return 0; 
} 

在您的測試您創建不依賴於任何類。然後你只用B測試界面這樣,你打破的一個模擬乙在C.創建不依賴下的模擬乙依賴是非常簡單的:

class MockB : public B { 
public: 
    MOCK_METHOD0(doSomething, void()); 
}; 
+0

好,但繁瑣的解決方案。如果可能的話,我寧願讓框架有一個自動化的宏...(在http://groups.google.com/group/googlemock/browse_thread/thread/2ed342a384456795上打開一個關於它的線程) – Jonathan 2011-04-25 11:38:11

+0

感謝接受答案。我認爲你想要的東西可能不可能用宏來做,因爲它需要宏來解析C++源代碼,因爲沒有可用的反射。 – mikelong 2011-04-25 11:58:10

+0

您可能需要閱讀googlemock cookbook上的界面:http://code.google.com/p/googlemock/wiki/CookBook#Alternative_to_Mocking_Concrete_Classes。 – User 2011-07-08 15:57:40