我正在使用谷歌模拟框架在c ++的串行应用程序上开发一些单元测试。
我为我的串口接口构建的模拟是:
class MockSerialPort: public SerialPortInterface {
public:
MOCK_METHOD0(Open, void());
MOCK_METHOD0(IsOpen,bool());
MOCK_METHOD4(Configure,void(int,int,int,SerialParity));
MOCK_METHOD0(Close,void());
MOCK_METHOD0(Read,queue<char>());
MOCK_METHOD1(RegisterSerialObserver,void(SerialObserver*));
MOCK_METHOD0(NotifySerialObserver,void());
MOCK_METHOD0(Die, void());
virtual ~MockSerialPort() {Die(); }
};
在我的实际实现中NotifySerialObserver的实现是:
void UnixSerialPort::NotifySerialObserver(){
this->serialManager->HandleSerialEvent(this->portID);
}
我正在使用的测试是:
TEST(SerialPortManagerTest,PortReadThrowsExceptionOnReadError){
PortID portID=COM1;
MockSerialPort* port1=new MockSerialPort();
EXPECT_CALL(*port1, Read()).Times(Exactly(1)).WillOnce(Throw(SerialPortReadErrorException()));
MockSerialPort* port2=new MockSerialPort();
MockSerialPort* port3=new MockSerialPort();
MockSerialPortFactory portFactory;
EXPECT_CALL(portFactory, CreateSerialPort(_)).Times(3).
WillOnce(ReturnPointee(&port1)).
WillOnce(ReturnPointee(&port2)).
WillOnce(ReturnPointee(&port3));
SerialPortManager* serialPortManager =new SerialPortManager((SerialPortFactoryInterface*)&portFactory);
<<<Need to add EXPECT_CALL on *port1->NotifySerialObserver() that invokes serialPortManager->HandleSerialEvent(COM1)>>>>
serialPortManager->OpenPort(portID);
EXPECT_THROW(port1->NotifySerialObserver(),SerialPortReadErrorException);
delete serialPortManager;
}
我需要测试当port1-&gt; NotifySerialObserver()被调用时,serialPortManager从port1读取。有没有办法从模拟的串口调用serialPortManager-&gt; HandleSerialEvent(COM1)?
编辑这是serialPortManager构造函数
SerialPortManager::SerialPortManager(
SerialPortFactoryInterface* serialPortFactory,SerialParserInterface* serialParser) {
this->serialPortFactory = serialPortFactory;
this->serialParser=serialParser;
for (int i = 0; i < PORT_COUNT; i++) {
ports[i] = serialPortFactory->CreateSerialPort((PortID) i);
cout << "Created port " << i << endl;
ports[i]->RegisterSerialObserver(this);
}
}
答案 0 :(得分:1)
首先,您需要重新构建测试,以确保在SerialPortManager
中创建MockSerialPortFactory
和SetUp()
并在TearDown()
中销毁。您还需要一个成员函数,使用HandleSerialEvent
上的正确参数调用SerialPortManager
:
class SerialPortManager : public Test
{
MockSerialPortFactory* portFactory;
SerialPortManager* serialPortManager;
protected:
virtual void SetUp()
{
portFactory = new MockSerialPortFactory();
serialPortManager = new SerialPortManager(portFactory);
}
virtual void TearDown()
{
delete serialPortManager;
delete portFactory;
}
void handleCOM1SerialEvent()
{
serialPortManager->HandleSerialEvent(COM1);
}
};
然后,您的测试可以在调用模拟串行端口时调用成员函数:
TEST(SerialPortManagerTest,PortReadThrowsExceptionOnReadError){
PortID portID=COM1;
MockSerialPort* port1=new MockSerialPort();
EXPECT_CALL(*port1, Read()).Times(Exactly(1)).WillOnce(Throw(SerialPortReadErrorException()));
MockSerialPort* port2=new MockSerialPort();
MockSerialPort* port3=new MockSerialPort();
EXPECT_CALL(*portFactory, CreateSerialPort(_)).Times(3).
WillOnce(Return(port1)).
WillOnce(Return(port2)).
WillOnce(Return(port3));
EXPECT_CALL(*port1, NotifySerialObserver()).
WillOnce(Invoke(this, &SerialPortManagerTest::handleCOM1SerialEvent));
serialPortManager->OpenPort(portID);
}
请注意,我不确定您的代码在CreateSerialPort
内调用SerialPortManager
的位置。如果在SerialPortManager
的构造函数内部调用它,那么您还必须将MockSerialPort
构造和销毁分别移动到SetUp()
和TearDown()
。
<强>更新强>
这是一个建议的实现,因为在CreateSerialPort
内调用了SerialPortManager
。我使用NiceMock
来摆脱无趣的模拟函数调用警告。为简单起见,我还将MockSerialPort
结构留在了测试体内。基本上,您必须确保在EXPECT_CALL
构建之前CreateSerialPort
SerialPortManager
发生:
class SerialPortManager : public Test
{
MockSerialPortFactory* portFactory;
SerialPortManager* serialPortManager;
protected:
virtual void SetUp()
{
portFactory = new NiceMock<MockSerialPortFactory>();
serialPortManager = nullptr; // Use NULL if not using C++11.
}
virtual void TearDown()
{
delete serialPortManager;
delete portFactory;
}
void createSerialPortManager()
{
serialPortManager = new SerialPortManager(portFactory);
}
void handleCOM1SerialEvent()
{
serialPortManager->HandleSerialEvent(COM1);
}
};
TEST(SerialPortManagerTest,PortReadThrowsExceptionOnReadError){
PortID portID=COM1;
MockSerialPort* port1=new MockSerialPort();
EXPECT_CALL(*port1, Read())
.Times(Exactly(1)).WillOnce(Throw(SerialPortReadErrorException()));
MockSerialPort* port2=new MockSerialPort();
MockSerialPort* port3=new MockSerialPort();
EXPECT_CALL(*portFactory, CreateSerialPort(_)).Times(3).
WillOnce(Return(port1)).
WillOnce(Return(port2)).
WillOnce(Return(port3));
createSerialPortManager();
EXPECT_CALL(*port1, NotifySerialObserver()).
WillOnce(Invoke(this, &SerialPortManagerTest::handleCOM1SerialEvent));
serialPortManager->OpenPort(portID);
}