用于resttemplate和retryTemplate的JAVA Mockito单元测试

时间:2019-02-27 22:16:15

标签: java unit-testing mockito resttemplate

我目前正在为以下方法编写单元测试

@Autowired
private RequestConfig requestConfig;

@Autowired
private RetryTemplate retryTemplate;

public ResponseEntity<String> makeGetServiceCall(String serviceUrl) throws Exception {
    try {
        return retryTemplate.execute(retryContext -> {

            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = requestConfig.createHttpHeaders();
            HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
            ResponseEntity<String> response = restTemplate.exchange(serviceUrl, HttpMethod.GET, entity, String.class);
            return response;

        });
    } catch (Exception e) {
        throw new Exception("Generic exception while makeGetServiceCall due to" + e + serviceUrl);
    }
}

更新方法:

@Autowired
private RequestConfig requestConfig;

@Autowired
private RetryTemplate retryTemplate;

@Autowired
private RestTemplate restTemplate;

public ResponseEntity<String> makeGetServiceCall(String serviceUrl) throws Exception {
    try {
        return retryTemplate.execute(retryContext -> {

            HttpHeaders headers = requestConfig.createHttpHeaders();
            HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
            ResponseEntity<String> response = restTemplate.exchange(serviceUrl, HttpMethod.GET, entity, String.class);
            return response;

        });
    } catch (Exception e) {
        throw new Exception("Generic exception while makeGetServiceCall due to" + e + serviceUrl);
    }
}

我尝试了所有可能的方法,但是我做对了。这是我的低下测试。

@Mock
private RestTemplate restTemplate;

@Mock
public RequestConfig requestConfig;

@InjectMocks
private RetryTemplate retryTemplate;

ServiceRequest serviceRequest;


@Test
public void makeGetServiceCall() throws Exception {
    String url = "http://localhost:8080";
    RetryTemplate mockRetryTemplate = Mockito.mock(RetryTemplate.class);
    RestTemplate mockRestTemplate = Mockito.mock(RestTemplate.class);
    ResponseEntity<String> myEntity = new ResponseEntity<>(HttpStatus.ACCEPTED);
    Mockito.when(mockRetryTemplate.execute(ArgumentMatchers.any(RetryCallback.class), ArgumentMatchers.any(RecoveryCallback.class), ArgumentMatchers.any(RetryState.class))).thenReturn(myEntity);

    Mockito.when(mockRestTemplate.exchange(
            ArgumentMatchers.eq(url),
            ArgumentMatchers.eq(HttpMethod.GET),
            ArgumentMatchers.<HttpEntity<String>>any(),
            ArgumentMatchers.<Class<String>>any())
    ).thenReturn(myEntity);

    ResponseEntity<String> response = serviceRequest.makeGetServiceCall(url);
    Assert.assertEquals(myEntity, response);
}

更新的测试案例:

 @Mock
public RequestConfig requestConfig;

@Mock
private RestTemplate restTemplate;

@Mock
private RetryTemplate retryTemplate;

@InjectMocks
ServiceRequest serviceRequest;

@Test
public void makeGetServiceCall() throws Exception {
    //given:
    String url = "http://localhost:8080";

    when(requestConfig.createHttpHeaders()).thenReturn(null);
    ResponseEntity<String> myEntity = new ResponseEntity<>( HttpStatus.ACCEPTED);
    when(retryTemplate.execute(any(RetryCallback.class), any(RecoveryCallback.class), any(RetryState.class))).thenAnswer(invocation -> {
        RetryCallback retry = invocation.getArgument(0);
        return retry.doWithRetry(/*here goes RetryContext but it's ignored in ServiceRequest*/null);
    });
    when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), eq(String.class)))
            .thenReturn(myEntity);

    //when:
    ResponseEntity<String> response = serviceRequest.makeGetServiceCall(url);

    //then:
    assertEquals(myEntity, response);
}

我从方法调用makeGetServiceCall获得的响应对象始终返回null。当我调试代码时,我在返回org.mockito.exceptions.misusing.WrongTypeOfReturnValue: ResponseEntity cannot be returned by toString() toString() should return String的{​​{1}}模拟中看到异常resttemplate错误,返回myEntity

我不确定我想念什么。

3 个答案:

答案 0 :(得分:1)

好吧,你犯了很多错误...

  1. 我确定您要使用private RetryTemplate retryTemplate;而不是@Mock来注释@InjectMocks
  2. @InjectMocks应该转到ServiceRequest serviceRequest;
  3. 您正在定义与mockRetryTemplate无关的某些mockRestTemplateserviceRequest上的交互。相反,您应使用带有@Mock注释的字段来定义交互,因为它们已被注入到您的被测对象(serviceRequest)中
  4. 此外,您通常无法模拟RestTemplate并将其注入到ServiceRequest中,因为您没有在RestTemplate中首先为ServiceRequest使用依赖项注入。您只需在ServiceRequest.makeGetServiceCall
  5. 中实例化其实例
  6. 您在第Mockito.when(retryTemplate.execute(...行中使用错误的方法定义了一个交互。您的互动指定了RetryTemplate.execute(RetryCallback, RecoveryCallback, RetryState),而您的ServiceRequest使用了另一种方法RetryTemplate.execute(RetryCallback)
  7. 您还应该注意,RetryTemplate.execute是最终版本,因此如here所述,如果没有额外的努力就不能嘲笑它。通常,与类相比,您应该更喜欢使用接口,例如RestOperationsRetryOperations分别位于RestTemplateRetryTemplate之上,以更加灵活。

也就是说,下面是解决您的问题的工作测试。但是请注意,从RestTemplate restTemplate = new RestTemplate();中删除ServiceRequest并将restTemplate设为一个字段,以便对其进行依赖注入。

@RunWith(MockitoJUnitRunner.class)
public class ServiceRequestTest {
    @Mock
    private RestTemplate restTemplate;

    @Mock
    public RequestConfig requestConfig;

    @Mock
    private RetryTemplate retryTemplate;

    @InjectMocks
    ServiceRequest serviceRequest;

    @Test
    public void makeGetServiceCall() throws Exception {
        //given:
        String url = "http://localhost:8080";
        ResponseEntity<String> myEntity = new ResponseEntity<>(HttpStatus.ACCEPTED);
        when(retryTemplate.execute(any(RetryCallback.class))).thenAnswer(invocation -> {
            RetryCallback retry = invocation.getArgument(0);
            return retry.doWithRetry(/*here goes RetryContext but it's ignored in ServiceRequest*/null);
        });
        when(restTemplate.exchange(eq(url), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class)))
                .thenReturn(myEntity);

        //when:
        ResponseEntity<String> response = serviceRequest.makeGetServiceCall(url);

        //then:
        assertEquals(myEntity, response);
    }
}

答案 1 :(得分:1)

对于下面的我来说,它工作正常,否则,它总是返回null

when(retryTemplate.execute(any(),any(),any())).thenAnswer(invocation -> {
        RetryCallback retry = invocation.getArgument(0);
        return retry.doWithRetry(null);
});

,导入为 import static org.mockito.ArgumentMatchers.any;

答案 2 :(得分:0)

通用解决方案:

Mockito.when(retryTemplate.execute(Matchers.any(),Matchers.any(),Matchers.any())).thenAnswer(invocation -> {
            RetryCallback retry = invocation.getArgumentAt(0,Matchers.any());
            return retry.doWithRetry(null);
        });