Java 使用mockito';s@mocks

Java 使用mockito';s@mocks,java,unit-testing,junit,mockito,Java,Unit Testing,Junit,Mockito,我有一个带有两个映射字段的抽象类。我想模拟并注入AbstractClass子类的对象中进行单元测试。另一个我真的不太在乎,但它有一个二传手 public abstract class AbstractClass { private Map<String, Object> mapToMock; private Map<String, Object> dontMockMe; private void setDontMockMe(Map<Stri

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

public abstract class AbstractClass {
    private Map<String, Object> mapToMock;
    private Map<String, Object> dontMockMe;

    private void setDontMockMe(Map<String, Object> map) {
        dontMockMe = map;
    }
}
公共抽象类AbstractClass{
私人地图制图室;
私人地图dontMockMe;
私有void setDontMockMe(映射){
dontMockMe=地图;
}
}

当使用@InjectMocks时,它会自动尝试按顺序注入:构造函数、setter、字段。它通过检查类型,然后检查名称(如果有多种类型的可能性),来检查是否可以在这些位置中注入。这对我来说不太好,因为我的模拟mapToMock实际上是通过其setter注入dontMockMe的。我无法编辑这个抽象类。我有办法避开塞特注射吗?提前谢谢你

这是一个极端情况,自动注入将不会像Mockito注入目前设计的那样工作。当存在多个相同类型的字段时,Mockito也有一些缺点


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

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

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

  • 如果只有类型为
    A
    的模拟,并且只有一个类型为
    A
    的setter,则将发生setter注入

  • 如果存在多个类型为
    A
    的mock或setter,它将尝试使用mock的类型和名称(通常是
    @mock
    字段名)查找匹配项。如果找到匹配项,则将发生注入

  • 然后,如果仍有一些模拟要注入,则可能会使用与setter相同的算法进行字段注入:

  • 如果只有类型为
    A
    的模拟,并且只有一个类型为
    A
    的字段,那么将发生字段注入

  • 如果存在多个模拟或类型为
    A
    的字段,它将尝试使用模拟的类型和名称(通常为
    @mock
    字段名称)查找匹配项。如果找到匹配项,则将发生注入


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

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

    Mockito injection是为简单、直接的设计而设计的

    在我看来,我错了:

  • 模拟
    映射
    ,一种您不拥有的类型,可能会导致许多问题
  • 在测试对象中只模拟单个映射,这意味着您的测试对测试对象的内部工作了解得太多

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

    为了纠正您编写的内容,Mockito首先尝试构造函数注入,然后尝试“setter and field”注入,模拟可以通过setter或直接注入字段。即使您没有这个setter,您仍然会有问题,因为Mockito会将您的mock注入这两个字段。