【问题标题】:Use Mockito to match a null list of a specific type使用 Mockito 匹配特定类型的空列表
【发布时间】:2016-10-13 23:47:11
【问题描述】:

我有一个需要几个参数的方法。其中之一是某个类的 List,null 是该参数的可接受值。

public void doStuff(String string, @Nullable List<SomeClass> list) {
    ...
}

我想编写一个测试,使用 Mockito 来验证该方法是否以 null 作为参数调用。我尝试使用isNull(List.class):

MyClass myClass = ...
verify(myClass).doStuff(any(String.class), isNull(List.class));

但这会产生警告:

未经检查的转换
需要:java.util.List
找到:java.util.List

如果列表不为空,我可以看到如何修复此警告:

// this generates the same warning
verify(myClass).doStuff(any(String.class), any(List.class));

// this does not generate the warning
verify(myClass).doStuff(any(String.class), Matchers.anyListOf(SomeClass.class)));

但是,我似乎找不到将这两种方法结合在一起的方法。或者找到一种替代方法来完成我想做的事情。 (除了用注释来抑制警告)

【问题讨论】:

  • 为什么null 列表永远是可接受的参数?不使用空列表的原因是什么?
  • 我同意这远非理想的设计决策。实际的方法要复杂得多,并且接受一长串可选参数。与其强迫某人创建十几个空列表,不如决定让他们通过 null 代替。当然,拥有多个方法或实现某种构建器或工厂会更有意义,但它是一个 Android 库,重点放在保持 APK 大小和 dex 数量低而不是可用性上。我很想在将来清理它,但现在这是我必须处理的。
  • 但是你现在需要一些时间来解决你的问题!为什么不使用它来重构此方法而不是尝试使模拟工作?我认为这完全值得花时间。顺便说一句,写Collections.emptyList() 而不是null 没什么大不了的?
  • 这是一个已经被多个客户端使用的API方法。如果不破坏已发布的应用程序,我无法删除它。但我确实想为它编写测试。

标签: java unit-testing mockito


【解决方案1】:

一般的答案是使用显式的泛型方法参数。

verify(myClass).doStuff(any(String.class), Matchers.<List<SomeClass>>isNull());

补充说明:

  • 实际上,警告并不能保护您免受任何伤害。 nullnull,并且通过类型擦除,所有这些形式都将编译为相同的字节码。
  • Java 8 可以从方法参数中推断出泛型类型,因此isNull() 就足够了,无需聪明。
  • Mockito 1.x 调用类 org.mockito.Matchers,而 Mockito 2.x 弃用该类以支持 org.mockito.ArgumentMatchers。在这两种情况下,匹配器方法都可以通过 org.mockito.Mockito 看到,但 static-methods-via-inheritance 在语义上很弱,可能会导致这些方法不显示在 IDE 中。
  • 如果没有 Matchers 作为静态参数,则无法指定 &lt;List&lt;SomeClass&gt;&gt;isNull()。你可以做什么,如果你需要做很多,就是提取一个本地静态方法......

    private static List<SomeClass> nullSomeClassList() {
      return isNull();  // Return value types can be inferred before Java 8.
    }
    
    // elsewhere
    verify(myClass).doStuff(any(String.class), nullSomeClassList());
    

    ...但不管你做什么,don't extract to a field instead。副作用在这里很重要。

【讨论】:

  • 感谢您的信息。我试过这个,但它导致了类似的问题。该代码生成了一个构建错误,抱怨该方法需要一个 List 并且它找到了一个 Object 。我尝试将匹配器的结果类型转换为 List 并解决了构建错误,但现在它仍然会生成未经检查的转换警告。这次它抱怨将 Object 转换为 List.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多