对于Mockito 2,是否应该使用ArgumentMarchers.any()而不是更具体的匹配器,例如ArgumentMatchers.anyString()或ArgumentMatchers.anyList()?是否应该使用特定的匹配器来提高代码的可读性?
根据经验,当使用本机objet (int、long、double、boolean)时,特定匹配器anyInt()、anyLong()、anyDouble()或anyBoolean()优先。但是其他的匹配者呢?有什么想法吗?谢谢。
发布于 2017-05-31 15:58:03
简而言之,在大多数情况下(尤其是在Java 8或更高版本中),您可以使用任何一种。any()对于非易碎的Mockito测试通常更为惯用,尽管使用anyString或any(String.class)有一些实用的原因和一些正确性的原因。注意:完整的基本原理深入研究了Mockito匹配器内部、Java类型参数推断和大量歇斯底里葡萄干。
对于像anyFloat()这样的原语,有一个非常实际的理由是选择anyFloat()等而不是any():后者会给您一个NullPointerException。对于像when(floatAcceptor.acceptFloat(any())).then(/*...*/)这样的Mockito语法,Mockito实际上会调用模拟的floatAcceptor.acceptFloat(float)方法,而对any()的调用必然会返回null 因为Mockito匹配器必须返回一个虚拟值。,而Java并没有告诉Mockito足够的信息来返回float-compatible值。不管是Mockito,Java都会尝试将一个null解压缩为一个float,然后失败。(anyFloat()和any(Float.class) float,因此它们正确地返回0.0f.)如果您知道一个值是一个原始的、装箱的或未装箱的,那么调用适当的方法就更安全了。对于List和String这两种对象来说,的原因就消失了,它们是贯穿始终的对象;Java将很高兴地传递从any接收到的null。
历史上,any与any(Class)、anyString()和anyList(Class)的行为相同;这是一个重要的方便,因为Java7无法从参数中推断类型参数,因此可以选择(Foo) any()或ArgumentMatchers.<Foo>any()。与之相比,any(Foo.class)更具可读性。对于列表来说,情况就更糟了,因为类型文本不支持其他类型,所以any(List.class)甚至不支持List<Bar>;您需要(List<Bar>) any()或ArgumentMatchers.<List<Bar>>any(),但是使用anyList,您只需编写anyList(Bar.class)就可以了。在所有情况下,参数都被完全忽略,要检查类型,需要使用isA(Class)进行反射、null-rejecting、instanceof-style检查。
然而,有两个改进改变了这一点:Java 8通过参数愉快地推断类型参数,所以any()更有用,Mockito修正了它的语法看起来更像英语。在英语中,“任何汽车”不太可能包括自行车或空停车位,但在Mockito 1.x中,any(Car.class)会很高兴地将调用与null或Bicycle实例匹配。因此,在Mockito2.x中,any(String)和anyString()只接受非null字符串正如GitHub问题185号中所记录的那样。所有其他any(Class)调用也是如此。
更重要的是,Mockito更喜欢灵活的测试,而不是脆弱的测试,因此您更可能看到any()作为不相关的Foo参数,而不是isA(Foo.class)或eq(new Foo())。如果更改参数不太可能影响所测试的行为,则约定忽略不相关的参数。尽管如此,当您知道参数不是anyString()时,anyList()和null可能对可读性很有用,还可以帮助您跟踪长参数列表,因为如果列表以与调用方法不兼容的方式更改时无法编译,则还可以帮助您跟踪长参数列表。
总之,:对原语使用原语方法,尽可能多地使用any(),但是如果要检查非null类型,则切换到any(Class)、any(List)或any(String)是正确的,如果您想提高可读性,或者需要维护长时间频繁更改的参数列表。
您可以更多地阅读any()、any(Class)和isA在这个GitHub问题的答案上的语义。
https://stackoverflow.com/questions/44287635
复制相似问题