2013-04-03 55 views
2

我需要写GTEST测试,有一个非虚方法,所以我现在用的是下面的源测试一些现有的代码,但我得到的编译错误模拟非虚方法让编译错误

package/web/webscr/sample_template_class3.cpp: In function âint main()â: package/web/webscr/sample_template_class3.cpp:64: error: âclass Templatemyclassâ has no member named âgmock_displayâ

sample_template_class3.cpp

#include <iostream> 
#include <gtest/gtest.h> 
#include <gmock/gmock.h> 

using namespace std; 

template < class myclass> 
class Templatemyclass 
{ 
    private: 
      myclass T; 
    public : 

     void display() 
     { 
      T.display(); 
     } 

}; 

class Test 
{ 
    public: 
     void display() 
     { 
      cout<<"Inside the display Test:" <<endl; 
     } 

}; 

class MockTest 

{ 
    public: 
       MOCK_METHOD0(display,void()); 
}; 

class FinalTest 
{ 
     public: 
         void show(Templatemyclass<Test> t) 
         { 
           t.display(); 
           cout<<"Inside the display FinalTest:" <<endl; 
         } 



}; 
int main() 
{ 


FinalTest test1; 
Templatemyclass<Test> obj1; 
Templatemyclass<MockTest> obj2; 
EXPECT_CALL(obj2,display()).Times(1); 
test1.show(obj1); 

return 1; 
} 

回答

3

有代码中的几个问题。我已经在下面进行了修改,并通过解释的方式评论了代码。如果这不够清楚,请添加评论,然后我会尝试进一步解释。

#include <iostream> 
#include <gtest/gtest.h> 
#include <gmock/gmock.h> 

using namespace std; 

template <class myclass> 
class Templatemyclass { 
private: 
    // Hold a non-const ref or pointer to 'myclass' so that the actual 
    // object passed in the c'tor is used in 'display()'. If a copy is 
    // used instead, the mock expectations will not be met. 
    myclass* T; 
public : 
    // Pass 'myclass' in the c'tor by non-const ref or pointer. 
    explicit Templatemyclass(myclass* t) : T(t) {} 
    void display() { T->display(); } 
}; 

class Test { 
public: 
    void display() { cout << "Inside the display Test:" << endl; } 
}; 

class MockTest { 
public: 
    MOCK_METHOD0(display, void()); 
}; 

class FinalTest { 
public: 
    // Templatise this function so we can pass either a Templatemyclass<Test> 
    // or a Templatemyclass<MockTest>. Pass using non-const ref or pointer 
    // again so that the actual instance with the mock expectations set on it 
    // will be used, and not a copy of that object. 
    template<class T> 
    void show(T& t) { 
    t.display(); 
    cout<<"Inside the display FinalTest:" <<endl; 
    } 
}; 

int main() { 
    Test test; 
    Templatemyclass<Test> obj1(&test); 

    MockTest mock_test; 
    Templatemyclass<MockTest> obj2(&mock_test); 
    EXPECT_CALL(mock_test,display()).Times(1); 

    FinalTest test1; 
    test1.show(obj1); 
    test1.show(obj2); 

    return 0; 
} 

下可能可能简化的情况:

#include <iostream> 
#include <gtest/gtest.h> 
#include <gmock/gmock.h> 

template <class myclass> 
class Templatemyclass { 
public: 
    myclass T; 
    void show() const { T.display(); } 
}; 

struct Test { 
    void display() const { std::cout << "Inside the display Test:\n"; } 
}; 

struct MockTest { 
    MOCK_CONST_METHOD0(display, void()); 
}; 

int main() { 
    Templatemyclass<Test> obj1; 
    obj1.show(); 

    Templatemyclass<MockTest> obj2; 
    EXPECT_CALL(obj2.T, display()).Times(1); 
    obj2.show(); 

    return 0; 
} 
+0

弗雷泽,你是伟大的!!!!!! :)非常感谢它正在工作.. – Gopal

+0

弗雷泽的另一个真棒答案!嘿,弗雷泽,我正在四处寻找有关如何在不使用模板的情况下模拟非虚拟方法的信息。我发现了一些非常有趣的答案,包括这两个:http://stackoverflow.com/a/2857770/1735836和http://stackoverflow.com/q/1127918/1735836。很想听听你的想法! – Patricia

+0

我想我会倾向尝试HippoMocks,但我在这里没有亲身经历。我们在代码库中使用了GoogleMock一段时间,并且设置和维护测试非常痛苦。例如,它对C++ 11智能指针确实不起作用。我听说过的另一种可能性是http://www.typemock.com/isolatorpp-product-page。这应该避免你为了测试而改变你的产品代码,但我不认为它是免费的,而且我没有亲身经历。除了那些,我会选择两个选项之一... – Fraser

0

如果你不想改变你的源代码,你可以利用injector++。 目前它只支持x86 Windows。但Linux和x64 Windows支持即将推出。下面的例子会给你一个简单的想法:

模拟非虚方法

下面的例子中使用fakeFunc()假货BaseClassTest::getAnInteger()

class FakeClassNonVirtualMethodTestFixture : public ::testing::Test 
{ 
public: 
    int fakeFunc() 
    { 
     return 6; 
    } 
}; 

TEST_F(FakeClassNonVirtualMethodTestFixture, FakeIntFunctionWhenCalled) 
{ 
    // Prepare 
    int expected = 6; 
    InjectorPP::Injector injector; 

    injector.whenCalled(INJECTORPP_MEMBER_FUNCTION(BaseClassTest::getAnInteger)) 
     .willExecute(INJECTORPP_MEMBER_FUNCTION(FakeClassNonVirtualMethodTestFixture::fakeFunc)); 

    BaseClassTest b = BaseClassTest(); 

    // Act 
    // FakeFunc will be executed! 
    int actual = b.getAnInteger(); 

    // Assert 
    EXPECT_EQ(expected, actual); 
} 

模拟虚拟方法

注射器++支持虚拟方法嘲讽(令人惊讶,呵呵?)。下面是一个简单的例子:

int FakeIntFuncForDerived() 
{ 
    return 2; 
} 

TEST_F(FakeClassVirtualMethodTestFixture, MockDerivedClassVirtualMemberFunctionWhenCalled) 
{ 
    // Prepare 
    int expected = 2; 
    BaseClassTest* derived = new SubClassTest(); 

    InjectorPP::Injector injector; 
    injector.whenCalledVirtualMethod(derived, "getAnIntegerVirtual") 
     .willExecute(fakeIntFuncForDerived); 

    // Act 
    // FakeIntFuncForDerived() will be exectued! 
    int actual = derived->getAnIntegerVirtual(); 

    // Assert 
    EXPECT_EQ(expected, actual); 

    delete derived; 
    derived = NULL; 
} 

模拟静态方法

注射器++支持静态方法嘲笑。下面是一个简单的例子:

Address FakeGetAnAddress() 
{ 
    Address addr; 
    addr.setAddressLine("fakeAddressLine"); 
    addr.setZipCode("fakeZipCode"); 

    return addr; 
} 

TEST_F(FakeClassNonVirtualMethodTestFixture, FakeStaticFunctionReturnUserDefinedClassWhenCalled) 
{ 
    // Prepare 
    Address expected; 
    expected.setAddressLine("fakeAddressLine"); 
    expected.setZipCode("fakeZipCode"); 

    InjectorPP::Injector injector; 

    injector.whenCalled(INJECTORPP_STATIC_MEMBER_FUNCTION(BaseClassTest::getAnAddressStatic)) 
     .willExecute(INJECTORPP_MEMBER_FUNCTION(FakeClassNonVirtualMethodTestFixture::fakeGetAnAddress)); 

    // Act 
    // FakeGetAnAddress will be executed! 
    Address actual = BaseClassTest::getAnAddressStatic(); 

    // Assert 
    EXPECT_EQ(expected, actual); 
}