我遇到了一个interresting,我认为我的测试代码中存在非常常见的同步问题。
这是测试(它是从外部连接到系统的功能测试),我是通过TestNG运行的。
@Test
public void operationalClientConnected_sendGetUserSessionRequest_clientShallReceiveGetUserSessionResponse() {
// GIVEN
OperationalClientSimulator client = operationalClientHasEstablishedWebSocketConnection("ClientXY");
// WHEN
GetUserSessionRequest request = PojoRequestBuilder.newRequest(GetUserSessionRequest.class).build();
client.sendRequest(request);
// THEN
assertThatClientReceivesResponse(client, GetUserSessionResponse.class, request.getCorrelationId(), request.getRequestId());
}
基本上我发送一个请求并等待正确的响应,这是我想在此测试中验证的内容。
在assertThatClientReceivesResponse
后面有一个看起来像这样的hamcrest匹配器:
@Override
protected boolean matchesSafely(final OperationalClientSimulator client) {
Object awaitedMessage = client.awaitMessage(
new Verification<Object>() {
@Override
public VerificationResult verify(final Object actual) {
VerificationResult result = new VerificationResult();
if (!_expectedResponseClass.isInstance(actual)) {
result.addMismatch("not of expected type", actual, _expectedResponseClass.getSimpleName());
}
// check more details of message ..
return result;
}
}, _expectedTimeout);
boolean matches = awaitedMessage != null;
if (matches) {
_messageCaptor.setActualMessage((T) awaitedMessage);
}
return matches;
}
现在对于interresting部分,OperationalClientSimulator
类中的同步。
有两种方法可以解决:
awaitMessage会阻塞,直到收到与给定验证匹配的邮件或超时已过期
onMessage收到的方法,为每个收到的消息(通过websocket连接)调用
基本上我想要实现的是在awaitMessage
方法上使用测试线程块,直到收到正确的消息(通过onMessage
)或指定的超时时间为止。
public Object awaitMessage(final Verification<Object> verification, final long timeoutMillis) {
// howto sync?
return awaitedMessage; // or null
}
@Override
public void onMessage(final String message) {
LOG.info("#Client {} <== received a message on websocket - {}", name, message);
// howto sync?
}
关于测试:
awaitMessage
方法收到响应我在考虑不同的同步解决方案:
我知道这是测试代码并且性能在这里不是真正的问题,我只是在考虑如何以“漂亮”的方式解决这个问题..你知道..因为它的圣诞节: - )
所以这里的实际问题是,我如何“安全”地等待我在测试中超时的消息?安全地这意味着我不会因为并发问题而错过消息或丢失消息,而且我还需要检查是否已收到预期的消息。
当在websocket连接上收到消息时,我应该如何在测试运行程序线程和onMessage
中调用OperationalClientSimulator
方法的线程之间进行同步。