2016-02-26 90 views
0

我想爲我們的項目單元測試環境。但我失去了如何爲班級成員製造嘲笑。我想用一個例子來解釋我的問題。如何嘲笑成員對象在C++

在我的舊項目,我們用的是模擬的選擇機制,在我看來是非常難看。下面是年長的方法:

class member { 
}; 

class member_mock_1 { 
}; 

class member_mock_2 { 
}; 

class parent { 
#if defined UNIT_TEST_1 
    typedef member_t member_mock_1; 
#elif defined UNIT_TEST_2 
    typedef member_t member_mock_2; 
#else 
    typedef member_t member; 
#endif 

private: 
    member_t mem; 
}; 

的第一個問題是嘲笑的成員對象的類與或縮小父類的typedefing是一個適當的方式或不?最佳做法是什麼?如果我想使用的單元測試框架,像GTEST,我應該用這種方式還是有另一種方式來嘲弄的成員?

注1:如果虛擬機制被激活,它是確定創建基類來緩解嘲諷,如果一個類是豆莢類的東西,我不想使用此機制。

注2:我也覺得醜傳遞類型的成員作爲模板參數,一切都變得項目模板。我不想這樣做。下面是一個例子:

template <typename M> 
class parent { 
private: 
    M mem; 
}; 

#if defined UNIT_TEST_1 
    typedef parent_t parent<member_mock_1>; 
#elif defined UNIT_TEST_2 
    typedef parent_t parent<member_mock_2>; 
#else 
    typedef parent_t parent<member>; 
#endif 

這裏是方法我建議這裏:

member_mock_1.hpp

class member_mock_1 { 
}; 

member_mock_2.hpp

class member_mock_2 { 
}; 

mock.hpp

template <typename TYPE> 
struct mock { using type = TYPE; }; 

#define ENABLE_MOCKING(NamE) \ 
using NamE ## _t = mock<NamE>::type 

member_mock.hpp

#if define UNIT_TEST_1 
    template<> 
    struct mock<member> { using type = member_mock_1 }; 
#endif 

#if define UNIT_TEST_2 
    template<> 
    struct mock<member> { using type = member_mock_2 }; 
#endif 

member.hpp

class member { 
}; 

ENABLE_MOCKING(member); 

parent.hpp我上面正常類作品都提到

class parent { 
private: 
    member_t mem; 
}; 

方法。對於模板類,我認爲應該完成一些額外的工作。

因此,作爲一個結論,我建議像上面的單元測試的結構。可能是不必要的,還有其他一些機制或方法可以滿足這一要求。也許我還是重新發明輪子:(

請建議您知道嘲諷類成員的方式

感謝

回答

1

是的,你重新發明輪子的代碼看起來非常凌亂:。

#if defined UNIT_TEST_1 
    typedef parent_t parent<member_mock_1>; 
#elif defined UNIT_TEST_2 
    typedef parent_t parent<member_mock_2>; 
#else 
    typedef parent_t parent<member>; 
#endif 

有幾個工具可用。 我使用Typemock隔離++,你可以模擬幾乎一切,而不需要任何接觸你的產品。 的另一件事,你在MOC設置行爲k僅適用於測試範圍,因此每個測試都有獨立和獨立的設置。

您可以訪問該成員,即使它是私有的:

member* mock_member = FAKE<member>; 
parent* my_parent = new parent(); 
ISOLATOR_SET_MEMBER(my_parent, mem, mock_member); 

,輕鬆地獲得它:

member* get_member; 
ISOLATOR_GET_MEMBER(my_parent, mem, get_member); 

而且,它允許假的抽象類,全局方法,純虛方法,私人和受保護的方法,爲它設置行爲。此外,訪問隱藏的數據成員並調用它們。查詢this瞭解更多信息。

0

聲明,我在Typemock工作。

山姆是完全正確的。 另外,您不需要爲每個單元測試創​​建3個不同的member_mock類。

你可以簡單地設置行爲,例如,對一些私有方法成員:

member* mock_member = FAKE<member>; 
PRIVATE_WHEN_CALLED(member, somePrivateMethod()).Return(0); 

下一頁使用PRIVATE_WHEN_CALLED(mock_member, somePrivateMethod())將超載行爲somePrivateMethod(),這樣,而不是創建不同的模擬量巨大 - 類只是改變你的需要的行爲。

希望它對你有用!

0

我和你有類似的情況 - 將單元測試引入傳統的C++項目。爲此,我使用了許多預處理指令以及Google TestGoogle Mock。特別是,如果我面對你的榜樣,我會做如下:

#if defined UNIT_TEST 
class imember 
{ 
    virtual void a_method() = 0; 
}; 
#endif 

class member 
#if defined UNIT_TEST 
: public imember 
#endif 
{ 
    void a_method() 
    { 
     // do something 
    }; 
}; 

class parent { 
public: 
#if defined UNIT_TEST 
    parent(imember mem) : mem_(mem) {}; 
#endif 

private: 
#if defined UNIT_TEST 
    imember mem_; 
#else 
    member mem_; 
#endif 
}; 

現在,使用谷歌模擬定義模擬類:

class mockmember : public imember 
{ 
public: 
    MOCK_METHOD0(a_method, void()); 
}; 

模擬類現在已準備就緒。使用Google測試來定義您的測試場景:

class parenttest : public testing::Test 
{ 
public: 
    parenttest() : member_(mockmember()), parent_(member_) {} 
    virtual void SetUp() {} 
    virtual void TearDown() {} 

protected: 
    parent parent_; 
    mockmember member_; 
}; 

TEST_F(parenttest, a_func) 
{ 
    EXPECT_CALL(member_, a_method()); 
    int ret = parent_.a_func(); 
    ASSERT_EQ(0, ret); 
}