java - Mockito 使用更改的列表进行验证

标签 java list collections mockito

我有一个简单的Bar,可以对某些字符串执行操作:

public interface Bar {

  void action(List<String> strings);

}

然后是我正在测试的 Foo。它随着时间的推移构建一个字符串列表,然后最终使用 Bar 来处理它们。当它们被处理后,队列被清除。

public class Foo {

  private final Bar bar;
  private final List<String> strings;

  public Foo(Bar bar) {
    this.bar = bar;
    this.strings = new ArrayList<>();
  }

  public void addStrings(String... strings) {
      Collections.addAll(this.strings, strings);
  }

  public void processStrings() {
    bar.action(strings);
    strings.clear();
  }

}

我正在尝试验证是否使用预期的字符串调用了Bar.action。但是,Mockito 不会检测带有实际参数的真正调用,因为调用 Bar.action 时使用的列表随后会被清除。

我可能做错了什么,但这对我来说就像一个错误。这是测试:

@Test
public void shouldVerify() {
    // Given
    Bar bar = mock(Bar.class);
    Foo foo = new Foo(bar);
    foo.addStrings("Hello", "World");
    foo.addStrings("!!!");
    // When
    foo.processStrings();
    // Then
    verify(bar).action(Arrays.asList("Hello", "World", "!!!"));
}

Comparison Failure:

Expected :bar.action([Hello, World, !!!]);

Actual :bar.action([]);

当然,注释掉 strings.clear() 可以让 Mockito 正确验证。


我可以通过创建一个新列表传递给 Bar 来解决这个问题,例如:

public void processStrings() {
  bar.action(new ArrayList<>(strings));
  strings.clear();
}

最佳答案

这里不太确定,但这似乎是 Mockito 的限制(但不要引用我的话)。起初我认为可以使用 ArgumentCaptor 来解决这个问题,但它捕获相同的实例,当您验证它时,它已经被修改了。

根据this answer您可以在调用方法时使用 Answer 来验证参数。由于 Bar::action 的返回类型为 void,因此对其进行 stub 需要稍微不同的方法。 Mockito docs建议使用 doX() 系列方法。

public void name() {
    Bar bar = mock(Bar.class);
    doAnswer(invocation -> {
        Object[] args = invocation.getArguments();
        List<String> list = (List<String>) args[0];
        assertThat(list.size(), is(3));
        return null;
    }).when(bar).action(anyList());

    Foo foo = new Foo(bar);
    foo.addStrings("Hello", "World");
    foo.addStrings("!!!");
    foo.processStrings();
}

doAnswer block 中,当列表传递给模拟时,您可以访问该列表。断言可以在那里完成,或者您可以存储参数并稍后再进行。我想说这个解决方案不是很优雅。

关于java - Mockito 使用更改的列表进行验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43601088/

相关文章:

java - 在 native c/c++ 代码中发生崩溃时,JVM 中的设置忽略 JRE 错误消息?

java - 如何在应用程序引擎上创建开发服务器

java - 使用 Eclipse 处理 Java 时出现 FileNotFoundException

Python - 基于键/值标识的分组/合并字典

arrays - Laravel 5 中 all() 和 toArray() 的区别

java用代理打开url需要很长时间

python - 从 python 中的列表中删除所有整数

java - 添加到列表时出现 NullPointerException

java - 如何通过构造初始化HashSet值?

java - 创建/排序 List<X>,其值的顺序与 List<Y> 中的顺序相同