gmock - 模拟派生类的非虚方法

时间:2015-03-12 10:34:47

标签: c++ unit-testing googlemock

我正在使用VS2005和gmock ver。 1.6用于单元测试。

我有以下代码,我想模拟,但我找不到这样做的方法。

class A
{
 virtual bool foo1() = 0;
 virtual bool foo2() = 0;
};

class B : public A
{
 virutal bool foo1();
 virtual bool foo2();
 static B* getInstance(int x);
 static B* getInstance();
}

getInstance(int x)只是创建B的实例并返回它。而getInstance()只是通过getInstance(int x);

返回已创建的实例

我有模拟课,

class MockA : public A
{
 MOCK_METHOD0(foo1, bool());
 MOCK_METHOD0(foo2, bool());
}

在消息来源中,我正在使用

bool retVal = B::getInstance()->foo2()

如何模仿此行为B::getInstance()

1 个答案:

答案 0 :(得分:0)

我认为你必须使用链接接缝来做你想做的事。

我们假设我们libraryToBeMocked的界面位于libraryToBeMocked.hpp

#pragma once

class Base
{
public:
    virtual bool evenCheck() = 0;
    virtual bool oddCheck() = 0;
};

class Derived : public Base
{
public:
    virtual bool evenCheck();
    virtual bool oddCheck();
    static Base* getInstance(int x);
    static Base* getInstance();

private:
    Derived(int x);

    int x;
};

你应该注意到我改变了你的设计。 getInstance方法都返回指向Base而不是Derived的指针。如果你想清楚地模拟逻辑,你应该模拟纯接口Derived已经有一些逻辑。恕我直言,无论如何都应将getInstance方法转移到其他类。

该库的实施位于libraryToBeMockedImpl.cpp

#include "libraryToBeMocked.hpp"

#include <memory>
#include <cstdlib>

bool Derived::evenCheck() { return x % 2 == 0; }

bool Derived::oddCheck() { return x % 2 != 0; }

namespace
{
    std::auto_ptr<Derived> current(NULL);
}

Base* Derived::getInstance(int x)
{
    current.reset(new Derived(x));

    return current.get();
}

Base* Derived::getInstance()
{
    return current.get();
}

Derived::Derived(int x) : x(x) {}

还有你想要测试的逻辑。 testedLibrary.hpp

#pragma once

bool isOdd(int x);
bool isEven(int x);

实施testedLibraryImpl.cpp

#include "testedLibrary.hpp"

#include "libraryToBeMocked.hpp"

bool isOdd(int x)
{
    return Derived::getInstance(x)->oddCheck();
}

bool isEven(int x)
{
    return Derived::getInstance(x)->evenCheck();
}

main中的虚假main.cpp

#include <iostream>

#include "testedLibrary.hpp"

using namespace std;

int main()
{
    int x;
    cin >> x;

    cout << x << " is odd:" << boolalpha << isOdd(x) << endl;
    cout << x << " is even:" << boolalpha << isEven(x) << endl;

    return 0;
}

我不使用VS,但我认为只需将main.cpp testedLibraryImpl.cpplibraryToBeMockedImpl.cpp添加到项目中即可。我宁愿使用gcc:

g++ main.cpp libraryToBeMockedImpl.cpp testedLibraryImpl.cpp -o production

好吧,让我们从我的回答开始吧。我会创建头文件&#39; libraryMockSeam.hpp&#39;:

#pragma once

#include "libraryToBeMocked.hpp"

class Provider
{
public:
    virtual Base* getInstance() = 0;
    virtual Base* getInstance(int x) = 0;
};

Provider* registerNewMockProvider(Provider*);

libraryMockSeam.cpp

#include "libraryMockSeam.hpp"

namespace
{
Provider* currentProvider = 0;
}

Provider* registerNewMockProvider(Provider* newProvider)
{
    Provider* t = currentProvider;
    currentProvider = newProvider;
    return t;
}

Base* Derived::getInstance()
{
    return currentProvider->getInstance();
}

Base* Derived::getInstance(int x)
{
    return currentProvider->getInstance(x);
}

正如您所看到的,此源文件提供了自己的getInstance方法实现。它将其委托给注册的提供商。标头引入了Provider接口和一个允许注册您的提供程序的功能。那就是它。

让我们看一下测试:

#include "testedLibrary.hpp"
#include "libraryMockSeam.hpp"

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

using namespace ::testing;

class MockProvider : public Provider
{
public:
 MOCK_METHOD1(getInstance, Base*(int x));
 MOCK_METHOD0(getInstance, Base*());
};

class MyMock : public Base
{
public:
 MOCK_METHOD0(evenCheck, bool());
 MOCK_METHOD0(oddCheck, bool());
};

class MyTestSuite : public Test
{
public:
    MyTestSuite()
    {
        registerNewMockProvider(&provider);
    }

    StrictMock<MyMock> mock;
    StrictMock<MockProvider> provider;
};

TEST_F(MyTestSuite, checksForOddValue)
{
    EXPECT_CALL(provider, getInstance(1)).Times(2).WillRepeatedly(Return(&mock));

    EXPECT_CALL(mock, evenCheck()).WillOnce(Return(false));
    EXPECT_CALL(mock, oddCheck()).WillOnce(Return(true));

    EXPECT_TRUE(isOdd(1));
    EXPECT_FALSE(isEven(1));
}

TEST_F(MyTestSuite, checksForEvenValue)
{
    EXPECT_CALL(provider, getInstance(1)).Times(2).WillRepeatedly(Return(&mock));

    EXPECT_CALL(mock, evenCheck()).WillOnce(Return(true));
    EXPECT_CALL(mock, oddCheck()).WillOnce(Return(false));

    EXPECT_TRUE(isEven(1));
    EXPECT_FALSE(isOdd(1));
}

我会像那样编译它:

g++ test.cpp testedLibraryImpl.cpp libraryMockSeam.cpp -lgmock -lgmock_main -lpthread -o test

您应该注意到我在这种情况下没有提供libraryToBeMocked.cpp,实施已由libraryMockSeam.cpp提供。如果你想使用整个库(即*.lib文件(或*.a))你将能够提供模拟库和接缝,但后来应该提供给链接器库。