java - Mockito、argThat 和 hasEntry

标签 java testing mockito hamcrest

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 参数调用服务的激活方法。

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
  }
}

我尝试测试的一些代码依赖于像这样的服务:

public interface Service {
  public void activate(Map<String, ?> params);
}

我想通过使用 Mockito 模拟服务并验证是否使用合理的映射调用了激活来测试此代码。以下代码有效:

@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);
}

但是,我只想测试 map 是否包含一个特定条目。哈姆克雷斯特 hasEntry matcher似乎非常适合这个用例:

@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 中收到以下错误:

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<String, ?> 的 Mockito 匹配器, 但是 hasEntry 给了我 Map<? extends String, ? extends String> 的匹配器.即使使用显式类型参数,我也不知道如何协调类型参数的“?扩展”部分。我应该怎么做才能解决此错误?我应该使用特定的强制转换或显式类型参数吗?

我知道我可以为此使用 ArgumentCaptor。这真的是唯一的方法吗?对于 Hamcrest 匹配器,这完全可能吗?

最佳答案

argThat由于某种原因未推断返回类型。尝试显式转换,如下所示:

 Mockito.verify(foo).bar((Map<String, String>) argThat(Matchers.hasEntry("paramName", "paramValue")));

testHasEntryCast()可以修复如下所示。注意 cast (Map<String, ?>)argThat返回类型:

@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")));
}

关于java - Mockito、argThat 和 hasEntry,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43288390/

相关文章:

java - 参数匹配器的使用无效!预期 0 个匹配器,记录 1 个

java - SonarQube 分析成功但未被服务器处理

java - 带有动态参数的自定义注释

java - 在java中使用sphinx4印地语语音到文本

java - 如何在mysql中存储当前日期和时间

javascript - Testcafe 更容易检查页面上是否存在类选择器

ruby - 从 Hook 文件运行 cucumber 测试

python - 未知错误 : Chrome failed to start: exited abnormally

java - 如何使用 Mockito 测试一个简单的给定方法

java - JUnit - 从类型转换返回模拟对象