我正在尝试执行一个单元测试,我需要我的模拟对象在一系列EXPECT_CALLS之后执行一个操作,或者作为其中一个序列上的操作,同时允许模拟的调用首先返回。
下面是我的非工作单元测试:
class MockWebSocket : public alert::QWebSocketInterface
{
public:
MOCK_METHOD(void, open, (QUrl const&), (override));
MOCK_METHOD(void, close, (QWebSocketProtocol::CloseCode, QString const&), (override));
MOCK_METHOD(qint64, sendTextMessage, (QString const&), (override));
MOCK_METHOD(QAbstractSocket::SocketState, state, (), (const, override));
MOCK_METHOD(QString, origin, (), (const, override));
MOCK_METHOD(QString, errorString, (), (const, override));
};
/*!
* @brief Defines a custom action, where we can invoke methods that were unrelated to a mock object's "expected call"
*/
ACTION_P3(InvokeUnrelatedMethodWith1Arg, classPointer, pointerToMemberFunc, first)
{
(classPointer->*pointerToMemberFunc)(first);
return 0; // This is being used as a return value from the mocked call. I want this action done AFTER the return instead!
};
/*
* @brief Test - Test if the state of the client is 'connected' after the CONNECTED frame is received
* Procedure:
* Call connect
* emit connected signal
* Send the CONNECT stomp frame
* Have the mock socket send back a CONNECTED stomp frame
* Check state
* Expected Results:
* State is CONNECTED
*/
TEST(ClientTests, ConnectedStateAfterConnectedFrame)
{
QByteArray connectedFrame =
"CONNECTED\n"
"version:1.2\n"
"session:714e58fb\n"
"server:ActiveMQ-Artemis/2.14.0\n"
"heart-beat:0,30000\n\n"
"\0";
auto mockWebsocket = std::make_shared<MockWebSocket>();
{
InSequence sequence;
EXPECT_CALL(*mockWebsocket, close(_, _)).Times(1);
EXPECT_CALL(*mockWebsocket, open(_))
.Times(1)
.WillOnce(InvokeWithoutArgs(mockWebsocket.get(), &MockWebSocket::connected));
EXPECT_CALL(*mockWebsocket, sendTextMessage(_))
.Times(1)
.WillOnce(DoAll(
Invoke([](QString message) {return message.size();}),
InvokeUnrelatedMethodWith1Arg(mockWebsocket.get(), &MockWebSocket::binaryMessageReceived,connectedFrame)
));
// Close is called during cleanup, so we have to allow more calls explicitly
EXPECT_CALL(*mockWebsocket, close(_, _)).Times(AtLeast(1));
}
auto client = std::make_unique<StompClientSideConnection>(mockWebsocket);
client->connect(QUrl("ws://localhost:5000"));
EXPECT_EQ(client->getState(), StompClientSideConnection::State::CONNECTING);
}这里的问题是,我在DoAll中执行的调用是在模拟方法返回之前执行的。返回值需要是消息的大小。
我需要在模拟调用返回后执行我的自定义操作。目前,我得到了模拟sendTextMessage的返回值0。
测试注释中描述了必须发生的事件的顺序。我想假装我正在模拟的套接字收到了响应我的连接请求的适当消息。有没有办法在模拟调用返回后执行操作?
发布于 2021-06-06 03:21:26
套接字通常是异步行为的(即,信号在调用方法之后的某个不确定时间发出),但您正在设置模拟对象,使其同步行为(信号在调用方法后立即发出)。您应该尝试模拟异步行为。
通常,您可以通过手动调用信号来实现此行为(而不是作为invoke子句的一部分):
TEST(ClientTests, ConnectedStateAfterConnectedFrame)
{
QByteArray connectedFrame =
"CONNECTED\n"
"version:1.2\n"
"session:714e58fb\n"
"server:ActiveMQ-Artemis/2.14.0\n"
"heart-beat:0,30000\n\n"
"\0";
auto mockWebsocket = std::make_shared<MockWebSocket>();
{
InSequence sequence;
EXPECT_CALL(*mockWebsocket, close(_, _)).Times(1);
EXPECT_CALL(*mockWebsocket, open(_))
.Times(1)
.WillOnce(InvokeWithoutArgs(mockWebsocket.get(), &MockWebSocket::connected));
EXPECT_CALL(*mockWebsocket, sendTextMessage(_))
.Times(1)
.WillOnce(DoAll(
Invoke([](QString message) {return message.size();}),
));
// Close is called during cleanup, so we have to allow more calls explicitly
EXPECT_CALL(*mockWebsocket, close(_, _)).Times(AtLeast(1));
}
auto client = std::make_unique<StompClientSideConnection>(mockWebsocket);
client->connect(QUrl("ws://localhost:5000"));
emit mockWebsocket->binaryMessageReceived(connectedFrame);
EXPECT_EQ(client->getState(), StompClientSideConnection::State::CONNECTING);
}您可能还需要考虑将此测试分成两个测试:一个测试客户端是否正确地启动了新连接,另一个测试客户端是否可以处理来自套接字的响应。
https://stackoverflow.com/questions/67840889
复制相似问题