模拟 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我遇到了同样的问题(至少有 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 给出错误 403?