原文: 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
依赖于DatabaseDAO
和NetworkDAO
。 当我们调用MainClass.save()
方法时,它在内部调用两个相关对象的保存方法。
3.1 Java 类
public class MainClass {
DatabaseDAO database;
NetworkDAO network;
//Setters and getters
public boolean save(String fileName)
{
database.save(fileName);
System.out.println("Saved in database in Main class");
network.save(fileName);
System.out.println("Saved in network in Main class");
return true;
}
}
public class DatabaseDAO {
public void save(String fileName) {
System.out.println("Saved in database");
}
}
public class NetworkDAO {
public void save(String fileName) {
System.out.println("Saved in network location");
}
}
3.2 MainClass
的 Junit 测试
让我们为MainClass
编写 junit 测试。
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMock;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class ApplicationTest
{
@InjectMock
MainClass mainClass;
@Mock
DatabaseDAO dependentClassOne;
@Mock
NetworkDAO dependentClassTwo;
@Before
public void init() {
MockitoAnnotations.initMock(this);
}
@Test
public void validateTest()
{
boolean saved = mainClass.save("temp.txt");
assertEquals(true, saved);
}
}
测试成功执行,我们在控制台中获得以下语句。 仔细观察控制台输出。
Saved in database in Main class
Saved in network in Main class
在上面的测试中,将打印用MainClass.save()
方法编写的语句,但不打印从属类。 它证明了方法主体仅针对MainClass
的save()
方法执行,因为我们使用@InjectMock
注解创建了MainClass
的实际对象。 对于依赖类,我们使用了模拟。
3.3 验证模拟的方法调用
要验证是否已调用模拟方法,我们必须使用模拟提供的工具方法verify()
。 它有助于验证在执行实际的测试类方法时是否已执行了模拟方法。
@Test
public void validateTest()
{
boolean saved = mainClass.save("temp.txt");
assertEquals(true, saved);
verify(dependentClassOne, times(1)).save("temp.txt");
verify(dependentClassTwo, times(1)).save("temp.txt");
}
4 总结
在此 mockito 教程中,我们了解了@Mock
和@InjectMock
注解之间的区别。 我们了解了在 junit 测试中将这些注解应用于类时发生了什么。
学习愉快!
参考: Mockito 指南