原文: https://howtodoinjava.com/mockito/mockito-mock-injectMock/

在使用 junit 和 Mockito 进行单元测试的过程中,我们使用@Mock@InjectMock注解来创建要测试的对象和依赖项。 了解 mockito 中@Mock@InjectMock注解之间的区别

1. 模拟对象与存根对象之间的区别

重要的是要了解模拟对象与存根对象之间的区别。 对象是类的实际实例,使用对象引用调用的任何方法都将执行类文件中定义的方法主体。

模拟对象是用于隐藏无法在测试环境中测试的依赖项的接口。 数据库,网络位置等。使用模拟引用调用的方法不会执行类文件中定义的方法主体,而是使用when-thenReturn方法组合来配置方法行为。

在 junit 测试中,我们为需要测试的类和要调用的方法创建对象。 我们为依赖项创建了模拟,这些依赖项不会出现在测试环境中,并且对象依赖于该依赖项来完成方法调用。

2. @Mock@InjectMock之间的区别

在基于 Mockito 的 junit 测试中,@Mock注解创建模拟,而@InjectMock创建类对象

@Mock – 创建模拟
@InjectMock – 创建对象并注入模拟的依赖项

  • 使用@InjectMock创建需要在测试类中进行测试的类实例。
  • 当需要为给定类执行实际方法主体时,请使用@InjectMock
  • 当我们需要使用模拟对象初始化的所有内部依赖项以正常工作方法时,请使用@InjectMock
  • 使用@Mock创建模拟,以支持要测试的类的测试。
  • 带有@Mock注解的带注解的类(待测试)依赖项。
  • 我们必须为模拟对象定义when-thenRetrun方法,在实际测试执行期间将调用哪些类方法。

3. @Mock@InjectMock示例

让我们通过示例来了解@Mock@InjectMock之间的区别。 在此示例中,我们具有类MainClass,其类具有方法save()

MainClass依赖于DatabaseDAONetworkDAO。 当我们调用MainClass.save()方法时,它在内部调用两个相关对象的保存方法。

3.1 Java 类

  1. public class MainClass {
  2. DatabaseDAO database;
  3. NetworkDAO network;
  4. //Setters and getters
  5. public boolean save(String fileName)
  6. {
  7. database.save(fileName);
  8. System.out.println("Saved in database in Main class");
  9. network.save(fileName);
  10. System.out.println("Saved in network in Main class");
  11. return true;
  12. }
  13. }
  1. public class DatabaseDAO {
  2. public void save(String fileName) {
  3. System.out.println("Saved in database");
  4. }
  5. }
  1. public class NetworkDAO {
  2. public void save(String fileName) {
  3. System.out.println("Saved in network location");
  4. }
  5. }

3.2 MainClass的 Junit 测试

让我们为MainClass编写 junit 测试。

  1. import static org.junit.Assert.assertEquals;
  2. import org.junit.Before;
  3. import org.junit.Test;
  4. import org.mockito.InjectMock;
  5. import org.mockito.Mock;
  6. import org.mockito.MockitoAnnotations;
  7. public class ApplicationTest
  8. {
  9. @InjectMock
  10. MainClass mainClass;
  11. @Mock
  12. DatabaseDAO dependentClassOne;
  13. @Mock
  14. NetworkDAO dependentClassTwo;
  15. @Before
  16. public void init() {
  17. MockitoAnnotations.initMock(this);
  18. }
  19. @Test
  20. public void validateTest()
  21. {
  22. boolean saved = mainClass.save("temp.txt");
  23. assertEquals(true, saved);
  24. }
  25. }

测试成功执行,我们在控制台中获得以下语句。 仔细观察控制台输出。

  1. Saved in database in Main class
  2. Saved in network in Main class

在上面的测试中,将打印用MainClass.save()方法编写的语句,但不打印从属类。 它证明了方法主体仅针对MainClasssave()方法执行,因为我们使用@InjectMock注解创建了MainClass的实际对象。 对于依赖类,我们使用了模拟。

3.3 验证模拟的方法调用

要验证是否已调用模拟方法,我们必须使用模拟提供的工具方法verify()。 它有助于验证在执行实际的测试类方法时是否已执行了模拟方法。

  1. @Test
  2. public void validateTest()
  3. {
  4. boolean saved = mainClass.save("temp.txt");
  5. assertEquals(true, saved);
  6. verify(dependentClassOne, times(1)).save("temp.txt");
  7. verify(dependentClassTwo, times(1)).save("temp.txt");
  8. }

4 总结

在此 mockito 教程中,我们了解了@Mock@InjectMock注解之间的区别。 我们了解了在 junit 测试中将这些注解应用于类时发生了什么。

学习愉快!

参考: Mockito 指南