Mock non-virtual method giving compilation error

…衆ロ難τιáo~ 提交于 2019-12-01 09:41:09

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

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