Mockito、argThat 和 hasEntry [英] Mockito, argThat, and hasEntry
问题描述
tl;dr:这些测试无法编译,因为类型参数不匹配.我应该进行哪些更改以使它们编译和运行正确吗?
tl;dr: These tests don't compile because the type parameters don't match. What changes should I make to make them compile and run correctly?
https://github.com/wesleym/matchertest
我有一些调用服务的非测试代码.它使用 map 参数调用服务的 activate 方法.
I have some non-test code that calls into a service. It calls the service's activate method with a map parameter.
public class Foo {
private final Service service;
public Foo(Service service) {
this.service = service;
}
public void bar() {
Map<String, ?> params = getParams();
service.activate(params);
}
private Map<String, ?> getParams() {
// something interesting goes here
}
}
我尝试测试的某些代码依赖于这样的服务:
Some code I'm trying to test has a dependency on a service like this one:
public interface Service {
public void activate(Map<String, ?> params);
}
我想通过使用 Mockito 模拟服务并验证使用合理的映射调用 activate 来测试此代码.以下代码有效:
I'd like to test this code by mocking the service with Mockito and verifying that activate was called with a reasonable map. The following code works:
@Test
public void testExactMap() {
Service mockService = mock(Service.class);
Foo foo = new Foo(mockService);
foo.bar();
Map<String, String> expectedParams = new HashMap<>();
expectedParams.put("paramName", "paramValue");
verify(service).activate(expectedParams);
}
但是,我只想测试地图是否包含一个特定条目.Hamcrest hasEntry matcher 似乎非常适合这个用例:
However, I'd like to just test that the map contains one particular entry. The Hamcrest hasEntry matcher seems perfect for this use case:
@Test
public void testHasEntry() {
Service mockService = mock(Service.class);
Foo foo = new Foo(mockService);
foo.bar();
verify(mockService).activate(argThat(hasEntry("paramName", "paramValue")));
}
当我尝试这个时,我在 IntelliJ IDEA 中收到以下错误:
When I try this, I get the following error in IntelliJ IDEA:
Error:(31, 45) java: incompatible types: inference variable T has incompatible bounds
equality constraints: java.util.Map<? extends java.lang.String,? extends java.lang.String>
upper bounds: java.util.Map<java.lang.String,?>,java.lang.Object
这里的问题是我需要一个 Map
Map
.即使使用显式类型参数,我也无法弄清楚如何协调类型参数的?扩展"部分.我应该怎么做才能解决这个错误?是否有我应该使用的特定类型转换或显式类型参数?
The problem here is that I need a Mockito matcher of Map<String, ?>
, but hasEntry gives me a matcher of Map<? extends String, ? extends String>
. Even with explicit type parameters, I can't figure out what to do to reconcile the "? extends" part of the type parameter. What should I do to resolve this error? Is there a specific cast or explicit type parameter I should use?
我知道我可以为此使用 ArgumentCaptor. 这真的是唯一的方法吗?对于 Hamcrest 匹配器,这完全可能吗?
I understand that I can use ArgumentCaptor for this. Is that really the only way to do this? Is this possible at all with Hamcrest matchers?
推荐答案
由于某种原因未推断 argThat
返回类型.尝试显式转换,如下所示:
The argThat
return type is not being inferred for some reason. Try explicitly casting as shown below:
Mockito.verify(foo).bar((Map<String, String>) argThat(Matchers.hasEntry("paramName", "paramValue")));
testHasEntryCast()
可以修复如下所示.注意 cast (Map
是 argThat
返回类型:
The testHasEntryCast()
can be fixed as shown below. Notice that cast (Map<String, ?>)
is to argThat
return type:
@Test
public void testHasEntryCast() {
Service mockService = mock(Service.class);
Foo foo = new Foo(mockService);
foo.bar();
verify(mockService).activate((Map<String, ?>) argThat(hasEntry("paramName", "paramValue")));
}
这篇关于Mockito、argThat 和 hasEntry的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!