如何将模拟对象注入另一个已经模拟过的对象

时间:2016-01-06 14:35:56

标签: java spring testing mockito

我有一个我这样嘲笑的课:

@Mock
private MyClass1 mockMyClass1;

说这个类看起来像这样:

public class MyClass1 {
  @Autowired
  private MyInnerClass myInnerClass;
}

当我模仿MyClass1时,MyInnerClass将被初始化为null。是否可以用另一个模拟对象来初始化该私有字段?我希望myInnerClass像这样嘲笑:

@Mock
private MyInnerClass myInnerClass;

如果我使用以下代码:

@InjectMocks
private MyClass1 mockMyClass1;
@Mock
private MyInnerClass myInnerClass

这会将MyInnerClass内的私有MyClass1初始化为模拟对象,但这种方式mockMyClass1不再是模拟本身,不是吗(我只是在真实类中注入一个模拟对象,就像@Autowired会注入一个真实对象一样)?如果我对@InjectMock@Mock的理解错了,你能纠正我的逻辑吗?我怎么能在另一个模拟对象中注入一个模拟对象(不使用setter / constructors)?

2 个答案:

答案 0 :(得分:7)

你误解了mock是什么。

当您模拟MyClass1时,模拟对象的类型MyInnerClass的内部字段不再存在。因此,尝试向模拟中注入某些内容是没有意义的。

通过说明与它交互时它应该做什么来控制模拟。您将其公共方法存根以执行您希望它们执行的操作。你给出了行为。唯一的默认行为(可能特定于Mockito)是在没有配置模拟的情况下返回null(但请注意它不会返回null因为某个内部变量是null },它返回,因为Mockito决定它应该返回;也许另一个模拟框架决定它应该抛出异常,谁知道?)。

举个例子,考虑一下你真正的班级是:

class MyClass1 {
    private MyInnerClass myInnerClass;
    public MyInnerClass getMyInnerClass() {
        return myInnerClass;
    }
}

现在考虑mock模拟该类。如果您致电mock.getMyInnerClass(),则 将是要调用的真实方法。它返回的是 myInnerClass的值。它将返回null,或者如果您使用

创建了该方法
when(mock.getMyInnerClass()).thenReturn(something);

然后它将返回something

所以回答你的问题:你不能这样做,因为这不是模拟的工作方式。

答案 1 :(得分:1)

您根本不应该使用InjectMocks注释(要了解原因,您可以阅读此article)。

您可以为MyClass1而不是Autowired字段实现Autowired构造函数。然后你可以简单地将MyInnerClass模拟引用作为构造函数参数传递。