模拟 resttemplate 交换总是返回 null

Posted

技术标签:

【中文标题】模拟 resttemplate 交换总是返回 null【英文标题】:mocking resttemplate exchange always returns null 【发布时间】:2019-08-30 14:53:40 【问题描述】:

我试图通过 mockito 模拟一个 restTemplate.exchange 方法,但无论我通过 mock 返回什么,它总是返回一个空值,即使我抛出异常:

这是实际代码:

ResponseEntity<List<LOV>> response = restTemplate.exchange(url, GET, null,new ParameterizedTypeReference<List<LOV>>() );

模拟代码:

 ResponseEntity<List<LOV>> mockResponse = new ResponseEntity<List<LOV>>(mockLovList() ,HttpStatus.ACCEPTED);

Mockito.when(restTemplate.exchange(any(), eq(GET), any(), ArgumentMatchers.<ParameterizedTypeReference<List<LOV>>>any())).thenReturn(mockResponse);

交换模拟中的每个参数都是 ArgumentMatchers 类型, mockLovList() 返回一个 LOV 列表

它应该返回我模拟的任何东西,但它总是返回 null

【问题讨论】:

【参考方案1】:

这是一个 RestTemplate.exchange() 模拟测试的工作示例:

import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
import java.util.List;

import static org.mockito.Mockito.*;

public class MyTest 

    @Test
    public void testRestTemplateExchange() 
        RestTemplate restTemplate = mock(RestTemplate.class);

        HttpEntity<String> httpRequestEntity = new HttpEntity<>("someString");

        List<String> list = Arrays.asList("1", "2");
        ResponseEntity mockResponse = new ResponseEntity<>(list, HttpStatus.ACCEPTED);
        when(restTemplate.exchange(anyString(), any(), any(), any(ParameterizedTypeReference.class), any(Object[].class)))
                .thenReturn(mockResponse);


        final ResponseEntity<List<String>> exchange = restTemplate.exchange("/someUrl", HttpMethod.GET, httpRequestEntity, new ParameterizedTypeReference<List<String>>() 
        );

        Assert.assertEquals(list, exchange.getBody());

    


【讨论】:

我在做同样的事情,但对我不起作用。我在另一个答案中评论了它在做 mockito.verify 时给出的错误 当我在实际交换调用中有第 5 个参数时它可以工作..这个参数 any(Object[].class),但如果第 5 个参数在实际交换方法中为空,我没有通过真正交换中最后一个参数中的任何内容都只调用 4 个参数,我不需要它【参考方案2】:

在设置或注入服务之前,您需要确保已初始化模拟。像这样-

@Mock
RestTemplate restTemplate;
@Before
public void init() 
    MockitoAnnotations.initMocks(this);
    userData = new UserService(restTemplate);

【讨论】:

这其实是正确答案【参考方案3】:

首先你可以使用验证方法调用是否正确

 Mockito.verify(restTemplate).exchange(any(), eq(GET), any(), any(ParameterizedTypeReference.class)))

Mockito 显示了一个非常漂亮的输出,包括实际的方法调用。

另外,您可以参考Deep Stubbing或Testing anonymous classes

【讨论】:

是的,这本身不起作用,它给出了 java.lang.reflect.InvocationTargetException 需要但未调用:restTemplate.exchange( , GET, , ); 然而,这个模拟只有 1 次交互:restTemplate.exchange("url", GET, null, ParameterizedTypeReference>【参考方案4】:

我遇到了同样的问题(至少有 2 个涉及这个问题),在寻找一个合理的答案后,我可以成功解决它。

在我解释之前,我将分享 2 个对我有帮助的解释。 How do I mock a REST template exchange? 和 Mocking RestTemplate.exchange() method gives null value。

所以,基本上,关键是每个涉及任何 RestTemplate 方法的测试用例都必须正确地给出每个参数。如果不行,Mockito 会失败并抛出这样的异常:

org.mockito.exceptions.misusing.PotentialStubbingProblem

或使用 NullPointerException 从 restTemplate.exchange 获取 ResponseEntity(这是你的情况)

之前(我隐藏了一些实现。Mockito 抛出了异常)

when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(), 
                    ArgumentMatchers.<ParameterizedTypeReference<FilterBean>>any())).thenReturn(responseEntityFilterBean);

Mockito 异常

org.mockito.exceptions.misusing.PotentialStubbingProblem:严格 存根参数不匹配。请检查:

此“交换”方法的调用: restTemplate.exchange( “/筛选”, 得到, , 类 br.com.test.bean.FilterBean ); -> 在 br.com.test.service.FilterService.getFilterStatus(FiltroService.java:60) 具有以下具有不同参数的存根:
    restTemplate.exchange("", null, null, null);

说明参数不对!

更改我的代码解决了我的问题。

                when(restTemplate.exchange(ArgumentMatchers.anyString(), 
                    ArgumentMatchers.any(HttpMethod.class),
                    ArgumentMatchers.any(), 
                    ArgumentMatchers.<Class<FilterBean>>any())).thenReturn(responseEntityFilterBean);

在你的情况下,尝试这样做,它会解决:

        when(restTemplate.exchange(ArgumentMatchers.anyString(), 
                    ArgumentMatchers.any(HttpMethod.class),
                    ArgumentMatchers.any(), ArgumentMatchers.<Class<List<String>>>any())))
            .thenReturn(mockResponse);

【讨论】:

以上是关于模拟 resttemplate 交换总是返回 null的主要内容,如果未能解决你的问题,请参考以下文章

模棱两可的方法调用模拟 RestTemplate.exchange()

如何获取通用地图作为来自 restTemplate 交换方法的响应?

RestTemplate请求出现401错误

为啥基本身份验证总是使用 restTemplate 给出错误 403?

为啥我在使用 RestTemplate 获取数据时总是得到 403? [复制]

如何模拟restTemplate getForObject