将仿制药与Mockito相匹配

Dar*_*ner 6 java spring unit-testing mockito

我试图嘲笑restTemplate.exchangeSpring Rest 的方法.

在同一个测试中,我有多个调用,它们只有返回类型不同.

以下是我创建的模拟方法

第一

// 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));
Run Code Online (Sandbox Code Playgroud)

第二

// 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));
Run Code Online (Sandbox Code Playgroud)

ParameterizedTypeReference模拟不考虑通用参数,最后定义的模拟胜过前者.

有没有办法使它工作?

Jef*_*ica 17

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

替换你的:

Matchers.<ParameterizedTypeReference<SearchResultsDTO<SolrDocumentDTO>>>any())
Run Code Online (Sandbox Code Playgroud)

有:

eq(new ParameterizedTypeReference<SearchResultsDTO<SolrDocumentDTO>>() {}))
Run Code Online (Sandbox Code Playgroud)

首先,Matchers.any()不匹配类型,甚至不是它的any(Foo.class)种类(从Mockito 1.x开始).any()匹配所有值,包括null和包括不正确的类型:

匹配任何对象,包括空值

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

("未来主要版本"可能会出现在Mockito 2中,isA可能会引入样式类型检查.;参见Mockito提交者Brice的评论.)

泛型有助于为exchange和获取正确的参数thenReturn,但由于类型擦除,没有任何类型的信息使其成为CLASS文件,更不用说JVM了.断言其参数类型的唯一匹配器是isA,它采用类文字并且不会帮助您参数化类型.

您可以编写一个自定义匹配器来检查参数的类型和类型参数,如果它们不受删除,但是对于您没有必要的特定情况.

类型擦除是ParameterizedTypeReference存在的全部原因:它将泛型信息捕获到子类中,其中参数化类型不会被擦除.此相同的模式被用于TypeToken在番石榴或TypeLiteral在吉斯.所有这些实现都将参数化类型描述为实例.

重要的是,所有的这些,包括ParameterizedTypeReference -支持equalshashCode,所以new ParameterizedTypeReference<A<B>>(){}等于new ParameterizedTypeReference<A<B>>(){}即使情况是不同的.(请参阅此处的代码.)

因为对相同参数化类型的引用是相同的,所以使用Mockito的eq匹配器使用不同的引用,事情应该没问题.