模拟休息模板进行单元测试

时间:2019-03-06 06:27:24

标签: spring rest spring-boot junit mockito

我想在Spring Boot中模拟RestTemplate,在其中我正在方法中进行REST调用。为了测试我正在创建的微服务的控制器, 我想在微服务的控制器中测试方法。

例如:

@GetMapping(value = "/getMasterDataView", produces = { MediaType.APPLICATION_JSON_VALUE })
@CrossOrigin(origins = { "http://192.1**********" }, maxAge = 3000)
public ResponseEntity<MasterDataViewDTO> getMasterDataView() throws IOException {

    final String uri = "http://localhost:8089/*********";

    RestTemplate restTemplate = new RestTemplate();
    MasterDataViewDTO masterDataViewDTO = restTemplate.getForObject(uri, MasterDataViewDTO.class);

    return new ResponseEntity<>(masterDataViewDTO, HttpStatus.OK);

}

我如何使用模拟测试呢?

这是我到目前为止所拥有的:

@Test
    public void testgetMasterDataView() throws IOException {

    MasterDataViewDTO masterDataViewDTO= mock(MasterDataViewDTO.class);
    //String uri = "http://localhost:8089/*********"; 

    Mockito.when(restTemplate.getForObject(Mockito.anyString(),ArgumentMatchers.any(Class.class))).thenReturn(masterDataViewDTO);

    assertEquals("OK",inquiryController.getMasterDataView().getStatusCode());        
}

运行模拟程序时出现错误,方法getMasterDataView()被调用,并且其中的REST调用也被调用并引发错误。如何编写测试,以便不调用REST端点?如果可能的话,我想和Mockito一起做。

2 个答案:

答案 0 :(得分:2)

在开始编写测试之前,应该对代码进行一些更改。首先,如果您提取了RestTemplate,并为其创建了一个单独的bean,然后将其注入到控制器中,将会容易得多。

为此,请在@Configuration类或主类中添加以下内容:

@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}

此外,您还必须从控制器中移除new RestTemplate(),并自动进行布线,例如:

@Autowired
private RestTemplate restTemplate;

现在您已经完成了,在测试中注入模拟RestTemplate会容易得多。

对于测试,您有两种选择:

  1. 使用模拟框架(例如Mockito)模拟RestTemplate和您尝试访问的所有方法
  2. 或者您可以使用MockRestServiceServer,它使您可以编写测试来验证URL是否被正确调用,请求是否匹配等等。

使用Mockito测试

要使用Mockito模拟RestTemplate,您必须确保在测试中添加以下注释:

@RunWith(MockitoJUnitRunner.class)

之后,您可以执行以下操作:

@InjectMocks
private MyController controller;
@Mock
private RestTemplate restTemplate;

现在您可以像这样调整测试:

@Test
public void testgetMasterDataView() throws IOException {
    MasterDataViewDTO dto = new MasterDataViewDTO();
    when(restTemplate.getForObject("http://localhost:8089/*********", MasterDataViewDTO.class)).thenReturn(dto);
    ResponseEntity<MasterDataViewDTO> response = controller.getMasterDataView();
    assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
    assertThat(response.getBody()).isEqualTo(dto);
}

您可以像在测试中一样模拟DTO,但不必这样做,而且我认为这样做不会带来任何好处。您只需要模拟restTemplate.getForObject(..)调用即可。

使用MockRestServiceServer

进行测试

另一种方法是使用MockRestServiceServer。为此,您必须在测试中使用以下注释:

@RunWith(SpringRunner.class)
@RestClientTest

然后,您必须自动连接控制器和MockRestServiceServer,例如:

@Autowired
private MyController controller;
@Autowired
private MockRestServiceServer server;

现在您可以编写如下测试:

@Test
public void testgetMasterDataView() throws IOException {
    server
        .expect(once(), requestTo("http://localhost:8089/*********"))
        .andExpect(method(HttpMethod.GET))
        .andRespond(withSuccess(new ClassPathResource("my-mocked-result.json"), MediaType.APPLICATION_JSON));
    ResponseEntity<MasterDataViewDTO> response = controller.getMasterDataView();
    assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
    // TODO: Write assertions to see if the DTO matches the JSON structure
}

除了测试您的实际REST调用是否匹配之外,这还允许您测试JSON到DTO是否也可以正常工作。

答案 1 :(得分:0)

您可以使用@RestClientTestMockRestServiceServer来实现。 their documentation中提供的示例:

@RunWith(SpringRunner.class)
@RestClientTest(RemoteVehicleDetailsService.class)
public class ExampleRestClientTest {

    @Autowired
    private RemoteVehicleDetailsService service;

    @Autowired
    private MockRestServiceServer server;

    @Test
    public void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails()
            throws Exception {
        this.server.expect(requestTo("/greet/details"))
                .andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
        String greeting = this.service.callRestService();
        assertThat(greeting).isEqualTo("hello");
    }

}