需要您输入以下内容: 我面临着一个关于如何为基类(StackBT)编写模拟的问题,在我想测试的派生类的构造函数(ApplicationBT)中创建了一个实例。 我的目的是为StackBT类(Mock_StackBT)编写一个模拟,然后将其链接到单元测试,以便在执行" new StackBT()"时创建模拟实例。在ApplicationBT的构造函数中。因此,使用它我可以在测试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();
}
答案 0 :(得分:0)
第一个问题是您在mockPtr_StackBT
中使用的是TestApplicationBT.cpp
,但它是在Mock_StackBT.cpp
中定义的
ApplicationBT::init
。第二个问题是对registerCallbacks
方法的调用调用函数
sendBTMacAddress
和mpoStackBT
通过指针ApplicationBT
,但如果你仔细观察
类StackBT
的构造函数,您将看到此指针设置为类Mock_StackBT
的对象
而不是registerCallbacks
。这会导致链接器错误,因为您没有实现函数
<{1}}和sendBTMacAddress
用于课程StackBT
,您只是声明了它们。
主要的问题是你没有用模拟交换真正的实现,你的方法是
不正确。首先,不要假设您为函数registerCallbacks
创建实现
和模拟类中的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
}
在构建单元测试可执行文件时,这将在编译期间执行交换实现。由于您在编写更多测试时将在几个类上执行此交换,因此我建议您将工厂函数包装在某个类中,该类提供所需类型的实现(模拟或生产)。例如,我的项目有一个名为ImplementationProvider
的类来执行此任务。