Java 是否不鼓励在同一领域使用 @Spy 和 @InjectMocks?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38567326/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:25:35  来源:igfitidea点击:

Is it discouraged to use @Spy and @InjectMocks on the same field?

javamockingmockito

提问by J. Schneider

In the project I'm working on right now, I often see the @Spyand @InjectMocksused together on a field. I have never seen it this way in any tutorials or other resources. I googled about this specific combination but didn't find anything else other than this thread on GitHub: https://github.com/mockito/mockito/issues/169

在我现在正在做的项目中,我经常看到@Spy@InjectMocks一起使用在一个领域。我从未在任何教程或其他资源中以这种方式见过它。我用谷歌搜索了这个特定的组合,但在 GitHub 上除了这个线程之外没有找到其他任何东西:https: //github.com/mockito/mockito/issues/169

Which makes me think we are using it in a weird way.

这让我觉得我们以一种奇怪的方式使用它。

Note: The reason why I think using both annotations together makes sense sometimes is because if you only use @InjectMocksMockito tries to instantiate the class with a no-args constructor. If you don't have a no-args contructor and add @Spyyou can use the object without needing an empty constructor.

注意:我认为有时同时使用两个注解有意义的原因是,如果您只使用@InjectMocksMockito,则会尝试使用无参数构造函数来实例化类。如果您没有无参数构造@Spy函数并添加,则可以使用该对象而无需空构造函数。

Edit: Another important use is that you can only stub methods if you just use both annotations.

编辑:另一个重要用途是,如果您只使用两个注释,则只能存根方法。

采纳答案by Jeff Bowman

It is uncommon, and arguably inappropriate, to use @Spy and @InjectMocks together.

将@Spy 和@InjectMocks 一起使用是不常见的,而且可以说是不合适的。

@InjectMocksworks as a sort of dependency injection for the system under test: If you have a test that defines a @Mock or @Spy of the right type, Mockito will initialize any fields in your @InjectMocks instance with those fields. This might be handy if you haven't otherwise structured your system-under-test for dependency injection (or if you use a DI framework that does field injection) and you want to replace those dependencies with mocks. It can be pretty fragile—unmatched fields will be silently ignored and will remain nullif not set in an initializer—but remains a decent annotation for your system under test.

@InjectMocks用作被测系统的一种依赖注入:如果您有一个定义了正确类型的 @Mock 或 @Spy 的测试,Mockito 将使用这些字段初始化 @InjectMocks 实例中的任何字段。如果您还没有为依赖注入构建被测系统(或者如果您使用执行字段注入的 DI 框架)并且您想用模拟替换这些依赖项,这可能会很方便。它可能非常脆弱——不匹配的字段将被默默忽略,null如果未在初始化程序中设置,将保留——但对于您的被测系统仍然是一个不错的注释。

@Spy, like @Mock, is designed to set up test doubles; you should use it when you have a collaborator that you want to stub or verify. Note there that @Spy and @Mock are always meant for dependencies, and not for your system under test.

@Spy与@Mock 一样,旨在设置测试替身;当您有想要存根或验证的合作者时,您应该使用它。请注意,@Spy 和 @Mock 始终用于依赖项,而不是用于您的被测系统

Ideally, you should not have any class that fulfills both roles in the same test, or else you may find yourself writing a test that painstakingly tests behavior that you've stubbed rather than actual production behavior. In any case it will be more difficult to tell exactly what the test covers versus the behavior you've stubbed.

理想情况下,您不应该有任何类在同一个测试中同时满足这两个角色,否则您可能会发现自己编写的测试会煞费苦心地测试您存根的行为而不是实际的生产行为。在任何情况下,都更难以准确判断测试涵盖的内容与您存根的行为。

Of course, this may not apply if you're trying to use Mockito to test a single method in isolation, and you want to stub calls to one method while testing the other. However, this might also be an indication that your class is violating the Single Responsibility Principle, and that you should break down the class into multiple independent classes that work together. Then, in your test, you can allow instances to have exactly one role and never need both annotations at once.

当然,如果您尝试使用 Mockito 单独测试单个方法,并且您想在测试另一个方法时存根对一个方法的调用,则这可能不适用。但是,这也可能表明您的类违反了单一职责原则,您应该将类​​分解为多个协同工作的独立类。然后,在您的测试中,您可以允许实例仅具有一个角色并且永远不需要同时使用两个注释。

回答by Brendan Kim

Each annotation has different purposes and they don't step on each other clearly as long as you need to use partial mocks. (a.k.a. stubbing related method(s) that has been already tested and/or trusted)

每个注解都有不同的目的,只要您需要使用部分模拟,它们就不会清楚地相互影响。(又名 stubbing 已经过测试和/或信任的相关方法)

For example, you have a class to test, which has dependency injection(s) that doesn't have to be real so you want to @InjectMocks. Besides, the method you are testing calls another method inside, which was already tested somewhere, or it calls external reference which was also tested most likely independently. So, you don't want to be bothered to test same method(s) more than once, and your test code should not be impacted by the out-of-scope implementation change anytime in the future.

例如,您有一个要测试的类,它具有不一定是真实的依赖注入,因此您想要@InjectMocks。此外,您正在测试的方法调用内部已经在某处测试过的另一个方法,或者它调用了最有可能独立测试的外部引用。因此,您不希望多次测试相同的方法,并且您的测试代码不应该在未来任何时候受到范围外实现更改的影响。

Only @Mock & @Spy, or @Mock & @InjectMocks pairs make no sense.

只有@Mock & @Spy 或@Mock & @InjectMocks 对没有意义。