使用莫吉托的@InjectMocks绕过二传手注射



我有一个带有两个Map字段的抽象类。一个我想模拟并注入到AbstractClass子类的对象中,用于单元测试。另一个我真的不太在乎,但它有一个二传手。

public abstract class AbstractClass {
    private Map<String, Object> mapToMock;
    private Map<String, Object> dontMockMe;
    private void setDontMockMe(Map<String, Object> map) {
        dontMockMe = map;
    }
}

当使用@InjectMocks时,它会自动尝试按顺序注入:构造函数、setter、字段。它通过检查类型来检查是否可以在这些地方注入,然后如果有多种类型的可能性则命名。这对我来说不太好用,因为我模拟的mapToMock实际上是通过它的setter注入到dontMockMe中的。我无法编辑这个抽象类。我有什么办法绕过二传手的注射吗?提前谢谢!

这是一个角落的情况,自动注入不会像Mockito注入目前设计的那样工作。当有多个字段具有相同的类型时,Mockito也会遇到一些缺点。


因此,为了理解为什么这不起作用,让我们深入了解Mockito执行注入的方式:

  1. 它将尝试通过构造函数注入来注入依赖项,如果成功,它将不会尝试以下步骤来保护新创建的实例免受最终的副作用。

  2. 然后,如果构造函数注入没有发生(没有arg构造函数,或者对象已经实例化),那么Mockito将查找mock和setter之间的匹配。但它必须做出一些选择才能自动发生。

    1. 如果只有A类型的mock,并且只有一个A类型的setter,则将发生setter注入。

    2. 如果有多个类型为A的mock或setter,它将尝试使用mock的类型和名称(通常是@Mock字段名)来查找匹配项。如果找到匹配项,则将进行注入。

  3. 然后,如果还有一些mock需要注入,则可能会使用与setter相同的算法进行字段注入:

    1. 如果只有A类型的mock并且只有一个A类型的字段,则将发生字段注入。

    2. 如果有多个mock或类型为A的字段,它将尝试使用mock的类型和名称(通常是@Mock字段名称)来查找匹配项。如果找到匹配项,则将进行注入。


目前,您的代码停留在2.1阶段,因为可能只有一个mock可用。

也就是说,对于Mockito的当前实现,没有真正优雅的解决方案,有必要自己编写注入代码。这实际上是Mockito注射的要点,如果注射太复杂或太奇怪,那么你必须把它写出来;编写这些样板代码实际上是质疑当前设计的最佳工具。

Mockito注射液是专为简单、笔直的设计而设计的。

在我看来,我发现错误:

  1. 模拟Map,一个你不拥有的类型,这可能会导致很多问题
  2. 只模拟测试对象中的单个映射,这意味着您的测试对测试对象的内部工作了解太多

如果你重构代码并让合作者出现,这将有利于设计。有了明确的依赖关系/协作者,它肯定也会使注入更加清晰。此外,测试应侧重于断言与合作者的交互,而不是如何数据实现,数据应仅作为给定输入的结果进行测试。

相关内容

  • 没有找到相关文章

最新更新