java - Mockito 模拟 RestTemplate 不使用返回模拟值

标签 java junit mockito resttemplate

相关代码如下:

服务代码:

@Override
public ResponseEntity<AppointmentResponse> createAppointment(AppointmentRequest partnerFulfillmentRequest) {

    RestTemplate rt                                 = null;
    ResponseEntity<AppointmentResponse> response    = null;
    String uri                                      = null;
    HttpEntity<AppointmentRequest> httpEntity       = null;
    HttpHeaders headers = null;
    try {
            rt = new RestTemplate();
            rt.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
            rt.getMessageConverters().add(new StringHttpMessageConverter());
            uri = new String(internalServiceUrl+"/"+APP_NAME_INTERNAL+"/appointment");
            log.info("Calling internal service URL : "+uri);
            headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            httpEntity = new HttpEntity<AppointmentRequest>(partnerFulfillmentRequest, headers);  
            response =  rt.exchange(uri, HttpMethod.PUT, httpEntity, AppointmentResponse.class);
            if (response != null)
            {
                log.info("Got response from internal servicec-->statusCode: "+response.getStatusCodeValue());
                log.info("Got response from internal service--> Body "+response.getBody());
            }


    }catch(HttpClientErrorException hceEx) {
        //hceEx.printStackTrace();
        AppointmentResponse res = new AppointmentResponse();
        return new ResponseEntity<AppointmentResponse>(mapResponse(hceEx.getResponseBodyAsString()), hceEx.getResponseHeaders(), hceEx.getStatusCode());
    }catch(Exception e) {
        e.printStackTrace();
        AppointmentResponse res = new AppointmentResponse();
        ResponseEntity<AppointmentResponse> wfmErrResponse = new ResponseEntity<AppointmentResponse>(res, HttpStatus.INTERNAL_SERVER_ERROR);
        log.error("ERROR WHILE CALLING INTERNAL SERVICE");
        log.error(uri);
        log.error(e);
        return wfmErrResponse;
    }
    return response;

}

测试代码:

@RunWith(MockitoJUnitRunner.class)
public class PartnerFulfillmentServiceImplTest {

@Mock
RestTemplate restTemplate;

@Mock
HttpHeaders httpHeaders;

@Mock
ResponseEntity responseEntity;

@InjectMocks
PartnerFulfillmentServiceImpl partnerFulfillmentService;

@Test
public void createAppointmentTest() {

    Whitebox.setInternalState(partnerFulfillmentService, "internalServiceUrl", "http://localhost:8080");

    AppointmentRequest appointmentRequest = new AppointmentRequest();
    appointmentRequest.setPartnerName("CENTRICITY");
    appointmentRequest.setTicketNumber("123ABC");

    httpHeaders = new HttpHeaders();
    httpHeaders.set("Content-type", "application/json");

    responseEntity = new ResponseEntity<>(
            "some response body",
            HttpStatus.OK
    );

    when(restTemplate.exchange(Mockito.anyString(),
            Mockito.<HttpMethod> any(),
            Mockito.<HttpEntity<?>> any(),
            Mockito.<Class<Object>> any()))
            .thenReturn(responseEntity);

    ResponseEntity<AppointmentResponse> response = partnerFulfillmentService.createAppointment(appointmentRequest);

    Assert.assertEquals(response.getStatusCode(), HttpStatus.OK);
}
}

我得到了 java.lang.断言错误: 预计:500 实际:200 这是可以理解的,因为它实际上并没有调用运行 .thenReturn(responseEntity); 逻辑。我的百万美元问题是,为什么?它应该返回responseEntity 值。我有 Exchange() 到 any() 的所有参数,希望尽可能频繁地触发条件,因为我总是可以在不同时间缩小条件范围。我没有正确 mock 我的restTemplate 吗?这是我目前对正在发生的事情的怀疑。任何建议都会有所帮助!

谢谢!

最佳答案

就像 @JB Nizet 指出的那样,您正在测试的方法中创建 RestTemplate 的新实例。这意味着将从新实例调用 exchange 方法,而不是模拟。如果包含方法 createAppointment 的类具有 RestTemplate 的依赖项注入(inject),您可以按照您所做的方式实现它。

您想要的是模拟 RestTemplate 新实例的构造函数,以便在创建新实例时将其替换。不幸的是,Mockito 无法模拟构造函数,因此您应该使用 PowerMockito用于模拟构造函数。

whenNew(RestTemplate.class).withNoArguments().thenReturn(restTemplate);

responseEntity = new ResponseEntity<>(
            "some response body",
            HttpStatus.OK
    );

when(restTemplate.exchange(Mockito.anyString(),
        Mockito.<HttpMethod> any(),
        Mockito.<HttpEntity<?>> any(),
        Mockito.<Class<Object>> any()))
        .thenReturn(responseEntity);

关于java - Mockito 模拟 RestTemplate 不使用返回模拟值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57084533/

相关文章:

java - 如何在 JUNIT 中检查字符串不为空

Java Mockito 与 RestTemplate.exchange 使用泛型

java - 如何验证使用 "null"参数调用 spy

java - 中断 shell 输出到文件

java - C# 数据到 Java

java - 设置 POST RequestMethod 时发送 GET 请求

android - 在测试期间使用 Mockito 模拟我类的一种方法

java - 使用 Jmeter 和 Junit 进行负载测试时,setUp 和tearDown 如何工作?

android - 如何在 Android Studio 中调试仪器测试?

java - Spring MVC。关于愿景解决方案/设计问题的问题