使用MockRestServiceServer时,无法精确测试服务调用的数量
我正在为服务调用编写一些重试逻辑,并尝试在单元测试中测试Rest模板是否尝试命中服务一定次数。我使用以下代码来执行测试使用MockRestServiceServer时,无法精确测试服务调用的数量,rest,spring-boot,junit,Rest,Spring Boot,Junit,我正在为服务调用编写一些重试逻辑,并尝试在单元测试中测试Rest模板是否尝试命中服务一定次数。我使用以下代码来执行测试 MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build(); mockServer.expect(ExpectedCount.times(5), method(HttpMethod.GET)) .andRespond(withServerError()); se
MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(ExpectedCount.times(5), method(HttpMethod.GET))
.andRespond(withServerError());
service.call();
我将重试逻辑设置为仅进行两次尝试。上面的测试代码要求它发生五次,但测试总是通过。事实上,我可以让这个测试失败的唯一方法是将预期计数设置为1(任何小于实际调用次数的值)。当我使用ExpectedCount.min
或ExpectedCount.between
时,也会出现同样的问题,因为只有当实际调用超过预期时,测试才会失败
我需要能够测试服务调用的确切数量,最好不使用Mockito。您可以使用所需的逻辑创建自己的ResponseCreator。例如:
class DelegateResponseCreator implements ResponseCreator {
private final ResponseCreator[] delegates;
private int toExecute = 0;
public DelegateResponseCreator(final ResponseCreator... delegates) {
this.delegates = delegates;
}
@Override
public ClientHttpResponse createResponse(final ClientHttpRequest request) throws IOException {
ClientHttpResponse ret = this.delegates[this.toExecute % this.delegates.length].createResponse(request);
this.toExecute++;
return ret;
}
}
此委托人按顺序执行响应的委托人
因此,您可以模拟您想要的呼叫号码的响应
mockServer.expect(ExpectedCount.times(5), MockRestRequestMatchers.method(HttpMethod.GET))
.andRespond(new DelegateResponseCreator(
MockRestResponseCreators.withServerError(),
MockRestResponseCreators.withServerError(),
MockRestResponseCreators.withServerError(),
MockRestResponseCreators.withServerError(),
MockRestResponseCreators.withSuccess()
));
在本例中,前四个调用将返回服务器错误,而第五个调用将成功 您需要在发出所有请求后调用
mockServer.verify()
,以检查是否满足期望。否则,您可以不提出任何请求而侥幸逃脱。这就是最终对我有效的方法,测试的最大尝试次数为4次:
MockRestServiceServer server;
@Before
public void setUp() {
server = MockRestServiceServer.bindTo(restTemplate).build();
}
@After
public void serverVerify() {
server.verify();
}
@Test
public void doWork_retryThenSuccess() throws Exception {
final String responseBody = "<some valid response JSON>";
final String url = BASE_URL + "/doWork";
server.expect(requestTo(url))
.andExpect(MockRestRequestMatchers.method(HttpMethod.POST))
.andRespond(ExceptionResponseCreator.withException(new SocketTimeoutException("first")));
server.expect(requestTo(url))
.andExpect(MockRestRequestMatchers.method(HttpMethod.POST))
.andRespond(ExceptionResponseCreator.withException(new IOException("second")));
server.expect(requestTo(url))
.andExpect(MockRestRequestMatchers.method(HttpMethod.POST))
.andRespond(ExceptionResponseCreator.withException(new RemoteAccessException("third")));
server.expect(requestTo(url))
.andExpect(MockRestRequestMatchers.method(HttpMethod.POST))
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
final MyResponseClass response = myService.call();
assertThat(response, notNullValue());
// other asserts here...
}
检查zed的答案是否准确。
package com.company.test;
import java.io.IOException;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.test.web.client.ResponseCreator;
import org.springframework.test.web.client.response.MockRestResponseCreators;
public class ExceptionResponseCreator extends MockRestResponseCreators {
public static ResponseCreator withException(IOException ex) {
return request -> { throw ex; };
}
public static ResponseCreator withException(RemoteAccessException ex) {
return request -> { throw ex; };
}
}