Mocking和Expecting来自使用Google Mock中的新运算符创建的Class实例



需要您对以下内容的输入:我面临的问题是如何为基类(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方法的调用调用函数registerCallbackssendBTMacAddress通过指针mpoStackBT,但如果您仔细查看在类ApplicationBT的构造函数中,您将发现该指针设置为类StackBT的对象而不是CCD_ 10。这会导致链接器错误,因为您没有实现函数对于类StackBTregisterCallbackssendBTMacAddress,您只声明了它们。

主要的问题是你没有用mock交换你的真实实现,你的方法是不正确。首先,不需要为函数registerCallbacks创建实现和mock类中的sendBTMacAddress,googlemock为您做这件事(文件mock_StackBT.cpp完全不必要)。此外,还需要StackBTMock_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的类来执行此任务。

最新更新