Mock non-virtual method giving compilation error

匿名 (未验证) 提交于 2019-12-03 02:29:01

问题:

I need to write the gtest to test some existing code that has a non-virtual method, hence I am testing using the below source, but I am getting the compilation error

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; }

回答1:

There are a couple of issues in your code. I have changed it below and commented the code by way of explanation. If this is not clear enough, add a comment and I'll try and explain further.

#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; }

The following could possibly simplify the case:

#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; }


回答2:

If you don't want to change your source code, you can leverage injector++. Currently it only supports x86 Windows. But Linux and x64 Windows support will come soon. Below examples will give you a brief idea:

Mock non-virtual methods

Below example fakes BaseClassTest::getAnInteger() by using fakeFunc():

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); }

Mock virtual methods

Injector++ supports virtual method mocking (Amazing, huh?). Below is a simple example:

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; }

Mock static methods

Injector++ supports static method mocking. Below is a simple example:

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); }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!