我想在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一起做。
在开始编写测试之前,您应该稍微更改一下代码。首先,如果你提取了RestTemplate
,并为你创建了一个单独的bean,你将在你的控制器中注入它将会容易得多。
为此,在@Configuration
类或主类中添加类似的内容:
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
此外,您必须从控制器中删除new RestTemplate()
,并将其自动装配,例如:
@Autowired
private RestTemplate restTemplate;
既然你已经这样做了,那么在你的测试中注入一个模拟RestTemplate
会容易得多。
对于您的测试,您有两种选择:
RestTemplate
和您尝试访问的所有方法MockRestServiceServer
,它允许您编写测试以验证URL是否被正确调用,请求是否匹配等等。要使用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-to-DTO是否也能正常工作。
你可以通过使用@RestClientTest
和MockRestServiceServer
来实现这一目标。 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");
}
}