模拟依赖类实质上是空的吗?

时间:2018-10-20 00:43:11

标签: junit dependency-injection mockito

作为Mockito Junit的初学者,这听起来可能是个很丢人的问题,但我还是想确认一下:

Class1 input1;

@Mock
Class2 input2;

private Class3 obj;

@Before
public void setup() {
    this obj = new Class3(input1, input2);
}

@Test
public void doTest() {
     val result1 = obj.method1(input1); // return sth.
     val result2 = obj.method2(input2); // return null.
}

因此将input1和input2传递到Class3 obj中,但是只有input2是模拟依赖项。然后,当我调用依赖于input2的method2时,发现它只是返回null。

那么任何嘲笑的类本质上都是null?这就是为什么我们需要在when ... thenReturn用于模拟类时使用?毕竟,我们的目的是测试主要功能,而不是依赖项。

我的理解正确吗?

2 个答案:

答案 0 :(得分:1)

是的,您的理解是正确的。

如果您使用了适当的运行器(junit4)或扩展名(junit5),则模拟对象也不为null(即使其toString方法可能返回类似于"null"的东西)。

但是,可能的问题是您的Class3#method2使用的Class2模拟方法返回了空值。

实际上,这种行为是需要的。在这里,您可以选择:

  • 使用注释@Mock (answer = Answers.RETURNS_DEEP_STUBS)使您的模拟返回深层存根,这种方式是Class2的任何方法(既不是最终方法,也不返回原始类型或包装类型)将返回一个模拟,并且该模拟的任何方法将返回一个模拟,依此类推。

  • 明确声明模拟应如何表现,例如:Mockito.when(input2.myMethod()).thenReturn("test");。由Mockito提供的subbing API的文档非常详尽:https://static.javadoc.io/org.mockito/mockito-core/2.23.0/org/mockito/Mockito.html#stubbing

希望这会有所帮助,

答案 1 :(得分:1)

模拟类不为null。它是具有与原始类相同签名的骨骼,但是没有实现。它可以“查看”对所有方法的调用,因此可以在以后进行验证。因此,模拟是一个不起作用的对象。它不能存储数据,也不能执行方法。您只能控制对其的所有调用以及该模拟的所有返回值。如果您需要一些更高级的模拟,则应使用@Spy。间谍是一个“模拟”,但具有原始实现:它是一种检测到的类,可检测对它的所有调用并控制输出,但BUT也具有原始存储功能和实际调用。

进行实际通话的另一种方法是通过这种构造: Mockito.when(myMockedObject).thenCallRealMethod();

在单元测试中,最佳实践是仅测试要测试的一个类,而不使用基础类。听起来像是一扇敞开的门,但实际上并非如此。您要测试的类所使用的所有类都应该被模拟。使用该模拟,您可以完全控制返回值,并且可以测试该类的所有极端情况。所有被模拟的类都应通过自己的单元测试进行测试。这就带来了下一个问题:测试使用的所有类都应该是可注入的或可更改的。您希望能够注入一个模拟,而不是真正的数据库驱动程序,以便查看是否进行了所有正确的调用。