【问题标题】:Mockito unit test for rest template用于休息模板的 Mockito 单元测试
【发布时间】:2019-10-28 19:52:33
【问题描述】:

我正在尝试为进行 http 调用的 rest 模板编写单元测试。我已经使用其余模板生成器创建了其余模板,如下所示。其余模板设置为配置读取和连接超时。我还有一个重试模板,用于在应用程序超时时执行重试。我已经指定了 http 方法:postForEntity、exchange 和 getForEntity,它们需要在重试模板中重试,并且需要帮助编写单元测试。我从 getForEntity 方法开始,但收到的输出与预期不同。对此的任何帮助都会有所帮助。

休息模板

 @Bean
public RestTemplate restTemplate() {
    return new RestTemplateBuilder()
            .setConnectTimeout(Duration.ofSeconds(10))
            .setReadTimeout(Duration.ofSeconds(10))
            .build();

}

正在重试 getForEntity

 public ResponseEntity getForEntity(URI uri, Class c) {
    return retryTemplate.execute(retryContext -> {
        return restTemplate.getForEntity(uri, c);
    });
}

单元测试

public class RetryRestTemplateTest {

@Mock
private RestTemplate restTemplate;

@Mock
private RetryTemplate retryTemplate;

private RetryRestTemplate retryRestTemplate;

String testUrl = "http://localhost:8080";

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);

    retryRestTemplate = new RetryRestTemplate(
            restTemplate,
            retryTemplate
    );
}

@Test
public void getForEntity() throws URISyntaxException{
    URI testUri= new URI(testUrl);
    ArgumentCaptor<URI> argument = ArgumentCaptor.forClass(URI.class);

    doReturn(new ResponseEntity<>("ResponseString", HttpStatus.OK))
            .when(restTemplate).getForEntity(any(URI.class), eq(String.class));

    assertThat(restTemplate.getForEntity(testUri, String.class), is(HttpStatus.OK));

    verify(restTemplate).getForEntity(argument.capture(), eq(String.class));
    assertThat(argument.getValue().toString(), is(testUri));
}}

我的预期应该是 而我的实际应该是 >

这方面的任何帮助都会有所帮助,因为我对 Mockito 和 Junit 没有那么丰富的经验。

【问题讨论】:

  • 您要验证/测试什么?
  • 我正在尝试测试 getForEntity 方法

标签: java unit-testing mockito resttemplate


【解决方案1】:

您的期望与您编写的代码不一致 getForEntity 不会返回 HttpStatus 实例,而是返回 ResponseEntity&lt;String&gt;。将 ResponseEntity&lt;String&gt;HttpStatus 进行比较永远不会产生相等的结果。

您的测试的固定版本:

  @Test
  public void getForEntity() throws URISyntaxException {
    URI testUri = new URI(testUrl);
    ArgumentCaptor<URI> argument = ArgumentCaptor.forClass(URI.class);

    doReturn(new ResponseEntity<>("ResponseString", HttpStatus.OK))
        .when(restTemplate).getForEntity(any(URI.class), eq(String.class));

    assertThat(restTemplate.getForEntity(testUri, String.class).getStatusCode(),
        CoreMatchers.is(HttpStatus.OK));

    verify(restTemplate).getForEntity(argument.capture(), eq(String.class));
    assertThat(argument.getValue(), CoreMatchers.is(testUri));
  }

一些旁注:该测试并没有真正测试getForEntity,它测试您使用mockito 创建的java 代理确实返回了模拟结果。恕我直言,您实际上是在测试模拟框架是否有效...

doReturn(new ResponseEntity<>("ResponseString", HttpStatus.OK)).when(restTemplate).getForEntity(any(URI.class), eq(String.class));

如 cmets 中所述,RestTemplate 的集成测试可能是:

package com.example.demo;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;

import java.io.IOException;
import java.net.URI;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

public class RetryRestTemplateTest {

  private final MockWebServer server = new MockWebServer();

  @BeforeEach
  public void setup() throws IOException {
    server.start();
  }

  @AfterEach
  public void teardown() throws IOException {
    server.close();
  }

  @Test
  public void getForEntity() {
    URI testUri = server.url("/").uri();
    server.enqueue(new MockResponse().setResponseCode(200).setBody("{}"));

    RestTemplate restTemplate = new RestTemplate();

    ResponseEntity<String> forEntity = restTemplate.getForEntity(testUri, String.class);
    assertThat(forEntity.getStatusCode(), is(HttpStatus.OK));
    assertThat(forEntity.getBody(), is("{}"));
  }
}

需要以下测试依赖:

<dependency>
  <groupId>com.squareup.okhttp3</groupId>
  <artifactId>mockwebserver</artifactId>
  <version>4.2.2</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>com.squareup.okhttp3</groupId>
  <artifactId>okhttp</artifactId>
  <version>4.2.2</version>
  <scope>test</scope>
</dependency>

【讨论】:

  • 感谢@Andreas 的帮助。我是单元测试的新手,您能帮忙测试一下 getForEntity 方法、exchange 方法和 postForEntity 方法吗?
  • 这只是个人喜好问题,但如果你想测试postForEntity,它具有进行http调用的可观察行为,我只会发布到一个真正的端点。有多种构建模拟端点的方法。我喜欢使用 github.com/square/okhttp/tree/master/mockwebserver 这会在 ms 内启动一个 http 服务器。
猜你喜欢
  • 2019-07-27
  • 1970-01-01
  • 1970-01-01
  • 2017-03-10
  • 1970-01-01
  • 2021-06-30
  • 2020-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多