【问题标题】:MockRestServiceServer simulate backend timeout in integration testMockRestServiceServer 在集成测试中模拟后端超时
【发布时间】:2016-05-06 15:26:15
【问题描述】:

我正在使用 MockRestServiceServer 在我的 REST 控制器上编写某种集成测试来模拟后端行为。 我现在想要实现的是模拟来自后端的非常慢的响应,这最终会导致我的应用程序超时。似乎可以使用 WireMock 实现,但目前我想坚持使用 MockRestServiceServer。

我正在创建这样的服务器:

myMock = MockRestServiceServer.createServer(asyncRestTemplate);

然后我在嘲笑我的后端行为:

myMock.expect(requestTo("http://myfakeurl.blabla"))
            .andExpect(method(HttpMethod.GET))
            .andRespond(withSuccess(myJsonResponse, MediaType.APPLICATION_JSON));

是否可以为响应添加某种延迟或超时或其他类型的延迟(或者可能是整个模拟服务器甚至我的 asyncRestTemplate)?或者我应该切换到 WireMock 还是 Restito?

【问题讨论】:

标签: java spring mocking mockito mockmvc


【解决方案1】:

您可以通过这种方式实现此测试功能(Java 8):

myMock
    .expect(requestTo("http://myfakeurl.blabla"))
    .andExpect(method(HttpMethod.GET))
    .andRespond(request -> {
        try {
            Thread.sleep(TimeUnit.SECONDS.toMillis(1));
        } catch (InterruptedException ignored) {}
        return new MockClientHttpResponse(myJsonResponse, HttpStatus.OK);
    });

但是,我应该警告您,由于 MockRestServiceServer 只是替换了 RestTemplate requestFactory,因此您所做的任何 requestFactory 设置都将在测试环境中丢失。

【讨论】:

  • 这个“requestTo()”方法在哪里?
  • @Tino org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo
  • 顺便说一句,您可以使用TimeUnit.SECONDS.sleep(1),这是一种可以自行执行 Thread.sleep 的便捷方法。
  • 正如您所提到的,如果您使用 OkHttp 或 Apache HTTP 组件等第三方库配置了 RestTemplate,这将不起作用。
  • 如果有人在寻找 Kotlin 版本,请将 return new MockClientHttpResponse(myJsonResponse, HttpStatus.OK); 替换为 withSuccess(myJsonResponse, APPLICATION_JSON).createResponse(request)
【解决方案2】:

如果您在 http 客户端中控制超时并使用例如 1 秒,您可以使用 mock server delay

new MockServerClient("localhost", 1080)
.when(
    request()
        .withPath("/some/path")
)
.respond(
    response()
        .withBody("some_response_body")
        .withDelay(TimeUnit.SECONDS, 10)
);

如果您想在 Mock Server 中断开连接,请使用 mock server error action

new MockServerClient("localhost", 1080)
.when(
    request()
        .withPath("/some/path")
)
.error(
    error()
        .withDropConnection(true)
);

【讨论】:

  • 这是使用完全不同的库?
【解决方案3】:

您可以采用的方法: 使用类路径资源或普通字符串内容指定响应正文。 Skeeve 上面建议的更详细的版本

.andRespond(request -> {
            try {
                Thread.sleep(TimeUnit.SECONDS.toMillis(5)); // Delay
            } catch (InterruptedException ignored) {}
            return withStatus(OK).body(responseBody).contentType(MediaType.APPLICATION_JSON).createResponse(request);
        });

【讨论】:

    【解决方案4】:

    Restito中,有一个模拟超时的内置函数:

    import static com.xebialabs.restito.semantics.Action.delay
    
    whenHttp(server).
       match(get("/something")).
       then(delay(201), stringContent("{}"))
    

    【讨论】:

      【解决方案5】:

      一般来说,您可以定义您的自定义请求处理程序,并在那里做一个讨厌的Thread.sleep()

      这在Restito 中是可能的。

      Action waitSomeTime = Action.custom(input -> {
          try {
              Thread.sleep(5000);
          } catch (InterruptedException e) {
              throw new RuntimeException(e);
          }
          return input;
      });
      
      whenHttp(server).match(get("/asd"))
              .then(waitSomeTime, ok(), stringContent("Hello World"))
      

      不过,不确定 Spring。您可以轻松尝试。检查DefaultResponseCreator 以获得灵感。

      【讨论】:

        猜你喜欢
        • 2012-04-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-07
        • 1970-01-01
        相关资源
        最近更新 更多