使用MockRestServiceServer时无法精确测试服务调用数

时间:2018-09-17 19:06:34

标签: rest spring-boot junit

我正在为服务调用编写一些重试逻辑,并尝试在单元测试中测试Rest Template正在尝试多次访问该服务。我正在使用以下代码执行测试。

MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
mockServer.expect(ExpectedCount.times(5), method(HttpMethod.GET))
  .andRespond(withServerError());

service.call();

我将重试逻辑设置为仅进行两次尝试。上面的测试代码要求它进行五次,但是测试始终会通过。实际上,使该测试失败的唯一方法是将期望计数设置为1(小于实际调用次数)。当我使用ExpectedCount.minExpectedCount.between时,会发生相同类型的问题,因为只有当实际调用超出预期时,测试才会失败。

我需要能够测试确切数量的服务呼叫,最好不使用Mockito。

3 个答案:

答案 0 :(得分:1)

这最终对我有用,最多尝试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...
}

我们被迫使用Spring Test 5.0.10,它没有MockRequestResponseCreators.withException()(在5.2.2中添加了方法)。从Spring 5.2.7代码中借用的,效果很好:

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; };
    }
}

答案 1 :(得分:0)

您可以使用所需的逻辑创建自己的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;
    }

}

此委托人按顺序执行ResponseDelegates。

因此,您可以模拟所需电话号码的响应

mockServer.expect(ExpectedCount.times(5), MockRestRequestMatchers.method(HttpMethod.GET))
            .andRespond(new DelegateResponseCreator(
                    MockRestResponseCreators.withServerError(), 
                    MockRestResponseCreators.withServerError(), 
                    MockRestResponseCreators.withServerError(), 
                    MockRestResponseCreators.withServerError(), 
                    MockRestResponseCreators.withSuccess()
                    ));

在此示例中,前四个调用将返回服务器错误,而第五个调用将成功。

答案 2 :(得分:0)

在发出所有请求以检查是否满足期望后,您需要致电mockServer.verify()。否则,您可以避免进行任何请求。