我正在使用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()
?
答案 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.cpp
和libraryToBeMockedImpl.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
))你将能够提供模拟库和接缝,但后来应该提供给链接器库。