需要您对以下内容的输入:我面临的问题是如何为基类(StackBT)编写mock,该基类的实例是在我想要测试的派生类的构造函数(ApplicationBT)中创建的。我的意图是为StackBT类(mock_StackBT)编写一个mock,然后将其链接到单元测试,以便在ApplicationBT的构造函数中执行"new StackBT()"时创建mock的实例。这样,我就可以在测试ApplicationBT类时模拟对StackBT类的期望。
out/linux_host/obj/TestApplicationBT.o: In function `TestApplicationBT::SetUp()':
tst/_src/TestApplicationBT.cpp:33: undefined reference to `mockPtr_StackBT'
out/linux_host/lib/libServer.a(ApplicationBT.o): In function `ApplicationBT::init()':
/_src/ApplicationBT.cpp:36: undefined reference to `StackBT::registerCallbacks()'
/_src/ApplicationBT.cpp:43: undefined reference to `StackBT::sendBTMacAddress(std::string)'
collect2: error: ld returned 1 exit status
make: *** [out/linux_host/bin/Test] Error 1
我在编译下面的代码片段时遇到了上面的编译器错误:
StackBT.h:
class StackBT
{
StackBT(){}
void registerCallbacks();
void sendBTMacAddress(std::string str);
}
Mock_StackBT.h:
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include <string>
using ::testing::NiceMock;
class Mock_StackBT;
extern NiceMock < Mock_StackBT >* mockPtr_StackBT;
class Mock_StackBT: public StackBT
{
Mock_StackBT(){}
MOCK_METHOD0(registerCallbacks, void());
MOCK_METHOD1(sendBTMacAddress, void(std::string str));
}
Mock_StackBT.cpp:
#include "Mock_StackBT.h"
NiceMock < Mock_StackBT >* mockPtr_StackBT;
void registerCallbacks()
{
mockPtr_StackBT->registerCallbacks();
}
void sendBTMacAddress(std::string str)
{
mockPtr_StackBT->sendBTMacAddress(std::string str);
}
ApplicationBT.h:
class ApplicationBT
{
public:
ApplicationBT() : mpoStackBT(new StackBT())
void init()
{
mpoStackBT->registerCallbacks();
mpoStackBT->sendBTMacAddress("AB:CD:EF:GH:IJ:KL");
}
friend class TestApplicationBT;
scoped_ptr<StackBT> mpoStackBT;
}
TestApplicationBT.h
class TestApplicationBT : public ::testing::Test
{
protected:
virtual void SetUp ()
{
mockPtr_StackBT = &stackBTMock;
ptrApplicationBT = new ApplicationBT();
}
void TearDown()
{
delete ptrApplicationBT;
}
public:
TestApplicationBT ()
{
}
~TestApplicationBT ()
{
ptrApplicationBT = NULL;
}
scoped_ptr<ApplicationBT> ptrApplicationBT;
StackBT* ptrStackBT;
NiceMock<Mock_StackBT> stackBTMock;
};
TEST_F(TestApplicationBT, Init)
{
EXPECT_CALL(stackBTMock, registerCallbacks() ).Times(1);
EXPECT_CALL(stackBTMock, sendBTMacAddress(_) ).Times(1);
ptrApplicationBT->init();
}
第一个问题是在TestApplicationBT.cpp
中使用mockPtr_StackBT
,但它是在Mock_StackBT.cpp
。第二个问题是对ApplicationBT::init
方法的调用调用函数registerCallbacks
和sendBTMacAddress
通过指针mpoStackBT
,但如果您仔细查看在类ApplicationBT
的构造函数中,您将发现该指针设置为类StackBT
的对象而不是CCD_ 10。这会导致链接器错误,因为您没有实现函数对于类StackBT
的registerCallbacks
和sendBTMacAddress
,您只声明了它们。
主要的问题是你没有用mock交换你的真实实现,你的方法是不正确。首先,不需要为函数registerCallbacks
创建实现和mock类中的sendBTMacAddress
,googlemock为您做这件事(文件mock_StackBT.cpp完全不必要)。此外,还需要StackBT
和Mock_StackBT
类的通用接口,以便交换机实现。以下是您的操作方法:
创建接口:
class IStackBT
{
public:
virtual IStackBT() {}
virtual void registerCallbacks() = 0;
virtual sendBTMacAddress(std::string str) = 0;
}
创建生产类:
class StackBT : public IStackBT
{
public:
void registerCallbacks() override
{
// Your code that registers callbacks
}
void sendBTMacAddress(std::string str) override
{
// Your code that sends mac address
}
}
创建模拟类:
class StackBTMock : public IStackBT
{
public:
MOCK_METHOD0(registerCallbacks, void());
MOCK_METHOD1(sendBTMacAddress, void(std::string str));
}
现在,让类ApplicationBT
包含一个IStackBT
指针,并使用某种形式的工厂方法创建真实对象或模拟对象,具体取决于您是否正在构建单元测试或部署代码。那里有几种方法,以下是我在gmock
项目中的做法。为单元测试创建预处理器定义指示代码是为单元测试构建的项目。例如,如果它被命名为MY_UNIT_TESTS
,那么在ApplicationBT
的构造函数执行以下操作:
ApplicationBT() : mpoStackBT(createStackBT())
其中createStackBT
是定义为的函数
IStackBT * createStackBT()
{
#ifdef MY_UNIT_TESTS
return new StackBTMock;
#else
return new StackBT;
#endif
}
当您构建单元测试可执行文件时,这将在编译期间执行实现的交换。由于在编写更多测试时,您将在几个类上执行这种交换,因此我建议您将工厂函数封装在某个类中,该类提供所需的类实现(mock或production)。例如,我的项目有一个名为ImplementationProvider
的类来执行此任务。