ArgumentMatchers.any() 与 Mockito 2 中的其他匹配器 [英] ArgumentMatchers.any() versus the other matchers in Mockito 2

查看:286
本文介绍了ArgumentMatchers.any() 与 Mockito 2 中的其他匹配器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于 Mockito 2,应该使用 ArgumentMarchers.any() 代替更具体的匹配器,例如 ArgumentMatchers.anyString()ArgumentMatchers.anyList() 例如?是否应该使用特定的匹配器来使代码更具可读性?

With Mockito 2, should ArgumentMarchers.any() be used instead of more specific matchers like ArgumentMatchers.anyString() or ArgumentMatchers.anyList() for example? Should specific matchers be used to make the code more readable?

根据经验,当使用原生对象(intlongdoubleboolean)时,特定匹配器anyInt()anyLong()anyDouble()anyBoolean() 是首选.但是其他匹配器呢?有任何想法吗?谢谢.

From experience, when using native objets (int, long, double, boolean), specific matchers anyInt(), anyLong(), anyDouble() or anyBoolean() is preferred. But what about the other matchers? Any ideas? Thanks.

推荐答案

简而言之,在大多数情况下(尤其是在 Java 8 或更新版本中),您可以使用任何一种.any() 对于非脆弱的 Mockito 测试通常更惯用,尽管使用 anyStringany(String.class) 有一些务实的原因和一些正确性的原因).当心:完整的基本原理深入研究了 Mockito 匹配器内部结构、Java 类型参数推断以及大量 歇斯底里的葡萄干.

In short, you could use either one in most cases (especially in Java 8 or newer). any() is often more idiomatic to non-brittle Mockito tests, though there are some pragmatic reasons and some correctness reasons to use anyString or any(String.class). Beware: the full rationale delves deeply into Mockito matcher internals, Java type parameter inference, and a whole lot of hysterical raisins.

对于像 anyFloat() 这样的原语,有一个非常实际的理由选择 anyFloat() 等而不是 any():后者会给你一个 NullPointerException.对于像 when(floatAcceptor.acceptFloat(any())).then(/*...*/) 这样的 Mockito 语法,Mockito 实际上会调用你模拟的 floatAcceptor.acceptFloat(float) 方法,并且对 any() 的调用必然返回 null 因为 Mockito匹配器必须返回一个虚拟值,而 Java 并没有告诉 Mockito 足够多的信息让它知道返回一个 float 兼容的值.不管 Mockito,Java 都会尝试将 null 拆箱为 float 并失败.(anyFloat()any(Float.class) 告诉 Mockito 期待 float,所以他们正确返回 0.0f.) 如果你知道一个值是一个原始值,装箱或拆箱,调用适当的方法会更安全.对于 ListString 来说,这个原因就消失了,它们是彻头彻尾的对象;Java 会很高兴地传递从 any 接收到的 null.

For primitives like anyFloat(), there is a very practical reason to prefer anyFloat() etc instead of any(): The latter will give you a NullPointerException. For Mockito syntax like when(floatAcceptor.acceptFloat(any())).then(/*...*/), Mockito will actually call your mocked floatAcceptor.acceptFloat(float) method, and calls to any() necessarily return null because Mockito matchers have to return a dummy value and Java doesn't tell Mockito enough for it to know to return a float-compatible value. Irrespective of Mockito, Java will try to unbox a null into a float and fail. (anyFloat() and any(Float.class) tell Mockito to expect a float, so they correctly return 0.0f.) If you know a value is a primitive, boxed or unboxed, it's safer to call the appropriate method. That reason goes away for List and String, which are objects through and through; Java will happily pass a null received from any.

过去,any 的行为与 any(Class)anyString()anyList(Class) 相同>;这是一个重要的便利,因为 Java 7 无法从参数推断类型参数,所以替代方案是 (Foo) any()ArgumentMatchers.any()代码>.与那些相比,any(Foo.class) 更具可读性.Lists 的情况更糟,因为类型字面量不支持其他类型,所以 any(List.class) 甚至不适用于 List;您需要 (List) any()ArgumentMatchers.>any(),但使用 anyList 您只需编写 anyList(Bar.class) 即可.在所有情况下,该参数都被完全忽略,要检查类型,您需要使用 isA(Class) 进行反射,null-rejecting, instanceof 样式检查.

Historically, any behaved identically to any(Class), anyString(), and anyList(Class); this was an important convenience, because Java 7 couldn't infer type arguments from parameters, so the alternative was (Foo) any() or ArgumentMatchers.<Foo>any(). Compared to those, any(Foo.class) is more readable. It gets even worse for Lists, because type literals don't support other types, so any(List.class) won't even work for List<Bar>; you'd need (List<Bar>) any(), or ArgumentMatchers.<List<Bar>>any(), but with anyList you can just write anyList(Bar.class) and be on your way. In all cases, the argument was entirely ignored, and to check types you'd need to use isA(Class) to do a reflective, null-rejecting, instanceof-style check.

然而,有两项改进改变了这一点:Java 8 很高兴通过参数推断类型参数,所以 any() 更有用,并且 Mockito 更正它的语法看起来更像英语.在英语中,任何汽车"不太可能包括自行车或空的停车位,但在 Mockito 1.x 中 any(Car.class) 会很高兴地将调用与 null<匹配/code> 或 Bicycle 实例.因此,在 Mockito 2.x 中,any(String)anyString() 将只接受非null 字符串,如 GitHub 问题 #185 中所述.与所有其他 any(Class) 调用相同.

However, two improvements happened that change this: Java 8 happily infers type arguments through parameters, so any() is much more usable, and Mockito corrected its syntax to appear more like English. In English, "any car" wouldn't likely include a bicycle or an empty parking spot, but in Mockito 1.x any(Car.class) would happily match invocations with a null or a Bicycle instance. Thus, in Mockito 2.x, any(String) and anyString() will only accept non-null Strings, as documented in GitHub issue #185. Same with all other any(Class) calls.

最重要的是,Mockito 更喜欢灵活的测试而不是脆弱的测试,因此与 Foo 参数相比,您更有可能看到 any() 表示不相关的 Foo 参数code>isA(Foo.class)eq(new Foo()).不相关的参数按照惯例会被忽略,如果更改它们不太可能影响被测试的行为.也就是说,当您知道参数不是 null 时,anyString()anyList() 对可读性很有用,并且还可以提供帮助如果您的列表以与您正在调用的方法不兼容的方式更改,您将无法编译,从而跟踪长参数列表.

To top it all off, Mockito prefers flexible tests rather than brittle ones, so you are much more likely to see any() for an irrelevant Foo parameter than isA(Foo.class) or eq(new Foo()). Irrelevant parameters are ignored by convention, if changing them is unlikely to affect the behavior being tested. That said, anyString() and anyList() can be useful for readability when you know the argument isn't null, and can also help you keep track of long argument lists by failing to compile if your list changes in an incompatible way to the method you're calling.

所以总结一下: 对原语使用原语方法,尽量使用any(),但切换到any(Class), any(List), or any(String) 如果你想检查非null类型是否正确,如果你想提高可读性, 或者你需要维护很长的经常变化的参数列表.

So in summary: Use primitive methods for primitives, use any() as much as possible, but switch to any(Class), any(List), or any(String) if you want to check non-null types are correct, if you want to improve readability, or you need to maintain long frequently-changing argument lists.

您可以在 这个 GitHub 问题答案.

You can read more on the semantics of any(), any(Class), and isA on this GitHub issues answer.

这篇关于ArgumentMatchers.any() 与 Mockito 2 中的其他匹配器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆