将泛型与Mockito匹配



我正在尝试模拟SpringRest.的restTemplate.exchange方法

在同一个测试中,我有多个调用,它们的不同之处仅在于返回类型。

以下是我创建的模型的方法

第一个

// 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));

mock不考虑ParameterizedTypeReference的通用参数,最后定义的mock胜过前者。

有什么办法让它发挥作用吗?

Mockito不擅长匹配泛型本身,但您的解决方案比一般情况容易得多。

更换您的:

Matchers.<ParameterizedTypeReference<SearchResultsDTO<SolrDocumentDTO>>>any())

带有:

eq(new ParameterizedTypeReference<SearchResultsDTO<SolrDocumentDTO>>() {}))

首先,Matchers.any()与类型不匹配。在Mockito 1.x中,any(Foo.class)甚至不匹配类型:any()匹配所有值,包括null和不正确的类型。

匹配任何对象,包括空

这个方法不使用给定的参数进行类型检查,它只是为了避免代码中的强制转换。然而,在未来的主要版本中,这可能会发生变化(可以添加类型检查)。

(旁注:在Mockito 2及更高版本中,any(Foo.class)具有类似英语的"any Foo"语义,使其行为更像isA(Foo.class)。)

泛型有助于为exchangethenReturn获得正确的参数,但由于类型擦除,这些类型信息都没有进入CLASS文件,更不用说JVM了。唯一断言其参数类型的Matcher是isA,它采用类文字,对参数化类型没有帮助。

您可以编写一个自定义Matcher来检查参数的类型和类型参数,如果它们不需要擦除,但对于您的特定情况,这是不必要的。

类型擦除是ParameterizedTypeReference存在的全部原因:它将泛型信息捕获到一个子类中,其中参数化类型将不会被擦除。同样的模式用于Guava中的TypeToken或Guice中的TypeLiteral。所有这些实现都将参数化类型描述为实例

重要的是,包括ParameterizedTypeReference在内的所有实例都支持equalshashCode,因此即使实例不同,new ParameterizedTypeReference<A<B>>(){}也等于new ParameterizedTypeReference<A<B>>(){}。(请参阅此处的代码。)

因为对同一参数化类型的引用是相等的,所以使用Mockito的eq匹配器和不同的引用,一切都会好起来。

相关内容

  • 没有找到相关文章

最新更新