java - 使用mockito的@InjectMocks绕过setter注入(inject)

标签 java unit-testing junit mockito

我有一个带有两个 Map 字段的抽象类。我想模拟并注入(inject) AbstractClass 子类的对象以进行单元测试。另一个我真的不太关心,但它有一个 setter。

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

    private void setDontMockMe(Map<String, Object> map) {
        dontMockMe = map;
    }
}

当使用@InjectMocks时,它会自动尝试按顺序注入(inject):构造函数、setter、字段。它通过检查类型来检查是否可以在每个位置注入(inject),然后在存在多种类型可能性时命名。这对我来说效果不太好,因为我的模拟 mapToMock 实际上是通过它的 setter 注入(inject)到 dontMockMe 中的。我无法编辑这个抽象类。有什么办法可以绕过 setter 注入(inject)吗?预先感谢您!

最佳答案

这是一个极端情况,自动注入(inject)无法按照 Mockito 注入(inject)当前的设计方式工作。当存在多个具有相同类型的字段时,Mockito 也会遇到一些缺点。


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

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

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

    1. 如果只有 A 类型的模拟,并且只有一个 A 类型的 setter,那么就会发生 setter 注入(inject)。

    2. 如果存在多个 A 类型的模拟或 setter ,它将尝试使用模拟的类型和名称(通常是 @Mock > 字段名称)。如果找到匹配项,就会发生注入(inject)。

  3. 然后,如果仍然有一些模拟需要注入(inject),则可能会发生字段注入(inject),使用与 setter 相同的算法:

    1. 如果只有 A 类型的模拟,并且只有一个 A 类型的字段,那么就会发生字段注入(inject)。

    2. 如果存在多个模拟或 A 类型的字段,它将尝试使用模拟的类型和名称(通常是 @Mock > 字段名称)。如果找到匹配项,就会发生注入(inject)。


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

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

Mockito 注入(inject)确实是为简单、直接的设计而设计的。

在我看来,我发现错误:

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

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

关于java - 使用mockito的@InjectMocks绕过setter注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17818035/

相关文章:

Java:如何对在方法范围内创建和操作文件的方法进行单元测试?

java - 输出文件新行不从下一行开始

java - 如何使用 Jsoup 解析仅包含一个类名的元素?

java - 使用 Java SSL 套接字的 Apple 推送通知

java - Java/Junit 中的异步单元测试 - 一个非常简单但不成功的示例

java - Java 中的单元测试 - 它是什么?

java - 使用 JUnit 进行单元测试

java - WebLogic 中未找到类异常,TomCat 中正常

Java:无法重绘()?

swift - 如何让我的 Swift 单元测试访问 Parse 的 SDK?