问题描述
我正在尝试模拟 Spring Rest 的 restTemplate.exchange
方法.
I'm trying to mock the restTemplate.exchange
method of Spring Rest.
在同一个测试中,我有多个调用,只是返回类型不同.
In the same test I have multiple calls which differ only by the return type.
这是我创建的模拟的方法
Here are the methods with the mocks I created
第一
// Original method
restTemplate.exchange(UrlMap.SEARCH + '?' + searchDocsForm.toQueryParams(),
HttpMethod.GET, null, new ParameterizedTypeReference<SearchResultsDTO<SolrDocumentDTO>>() {
})
// Mock
when(restTemplate.exchange(any(String.class), any(HttpMethod.class), any(), Matchers.<ParameterizedTypeReference<SearchResultsDTO<SolrDocumentDTO>>>any())).thenReturn(
new ResponseEntity<>(searchResultsDTO, HttpStatus.OK));
第二
// Original method
restTemplate.exchange(UrlMap.ALL_DOCUS_TOPICS,
HttpMethod.GET, null, new ParameterizedTypeReference<List<SelectItem>>() {
}).getBody();
// Mock
when(restTemplate.exchange(any(String.class), any(HttpMethod.class), any(), Matchers.<ParameterizedTypeReference<List<SelectItem>>>any())).thenReturn(
new ResponseEntity<>(selectItems, HttpStatus.OK));
ParameterizedTypeReference
的泛型参数不被mock考虑,最后定义的mock胜过前者.
The generic parameters of ParameterizedTypeReference
are not considered by the mock, and the last defined mock wins over the former.
有没有办法让它工作?
推荐答案
Mockito 本身并不擅长匹配泛型,但你的解决方案比一般情况要容易得多.
Mockito isn't good at matching generics itself, but your solution is much easier than the general case.
替换你的:
Matchers.<ParameterizedTypeReference<SearchResultsDTO<SolrDocumentDTO>>>any())
与:
eq(new ParameterizedTypeReference<SearchResultsDTO<SolrDocumentDTO>>() {}))
<小时>
首先,Matchers.any()
不匹配类型,甚至在它的 any(Foo.class)
变体中也不匹配(从 Mockito 1.x).any()
匹配 所有值,包括 null并包括不正确的类型:
First of all, Matchers.any()
doesn't match type, not even in its any(Foo.class)
variety (as of Mockito 1.x). any()
matches all values, including null
and including incorrect types:
匹配任何对象,包括空值
Matches any object, including nulls
此方法不对给定参数进行类型检查,它只是为了避免在代码中进行强制转换.但是,这可能会在未来的主要版本中发生变化(可能会添加类型检查).
This method doesn't do type checks with the given parameter, it is only there to avoid casting in your code. This might however change (type checks could be added) in a future major release.
(未来的主要版本"可能会在 Mockito 2 中实现,其中可能会引入 isA
样式的类型检查.;请参阅 来自 Mockito 提交者 Brice 的评论.)
(The "future major release" may come true for Mockito 2, where isA
-style type checks may be introduced. ; See commentary from Mockito committer Brice.)
泛型有助于为 exchange
和 thenReturn
获取正确的参数,但由于 类型擦除 没有任何类型信息进入 CLASS 文件,更不用说 JVM.唯一断言其参数类型的匹配器是 isA
,它采用类字面量,对参数化类型没有帮助.
The generics are helpful to get the right parameter for exchange
and thenReturn
, but because of type erasure none of that type information makes it into the CLASS file, let alone the JVM. The only Matcher that asserts the type of its argument is isA
, which takes a class literal and won't help you for parameterized types.
您可以编写一个自定义 Matcher 来检查参数的类型和类型参数(如果它们不受擦除),但对于您的特定情况,这不是必需的.
You could write a custom Matcher that inspects an argument's type and type parameters, if they aren't subject to erasure, but for your specific case that's not necessary.
类型擦除是全部原因 ParameterizedTypeReference 存在:它将泛型信息捕获到子类中,其中参数化类型不会被擦除.TypeToken 在 Guava 或 Guice 中的 TypeLiteral.所有这些实现将参数化类型描述为实例.
Type erasure is the whole reason ParameterizedTypeReference exists: It captures the generics information into a subclass, where the parameterized type will not be erased. This same pattern is used for TypeToken in Guava or TypeLiteral in Guice. All of these implementations describe a parameterized type as an instance.
重要的是,所有这些——包括 ParameterizedTypeReference——支持equals
和hashCode
,所以new ParameterizedTypeReference<A<B>>(){}
等于 new ParameterizedTypeReference<A<B>>(){}
,即使实例不同.(见这里的代码.)
Importantly, all of them—including ParameterizedTypeReference—support equals
and hashCode
, so new ParameterizedTypeReference<A<B>>(){}
equals new ParameterizedTypeReference<A<B>>(){}
even though the instances are different. (See the code here.)
因为对同一个参数化类型的引用是相等的,所以使用 Mockito 的 eq
匹配器和不同的引用,应该没问题.
Because references to the same parameterized type are equal, use Mockito's eq
matcher with a different reference, and things should be fine.
这篇关于将泛型与 Mockito 匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!