目录
1.概述
2.使用
2.1.依赖
2.2.校验
2.2.1.值校验
2.2.2.顺序校验
2.2.3.指定返回
2.3.注解
2.3.1.@Mock
2.3.2.@Spy
2.3.3.@Captor
2.3.4.@InjectMocks
1.概述
mock,一种JAVA单元测试技术,mock允许使用模拟对象替换测试中的系统部件,并断言它们是如何被使用的一项技术。
当某个接口或者功能模块依赖于其他接口或者模块,而所依赖的模块或接口未开发完毕,可以使用mock模拟依赖的模块。
mockito,JAVA单元测试中使用频率最高的mock框架之一。
mock遵循流程:输入—期望—验证
2.使用
2.1.依赖
注释:博主用的3.8.0,具体版本号有哪些可以去maven repository上查。
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${version}</version>
<scope>test</scope>
</dependency>
2.2.校验
2.2.1.值校验
校验值是否是期待值。
2.2.2.顺序校验
inOrder可以校验方法的调用顺序是否是按照之前的调用顺序。
2.2.3.指定返回
指定返回值是mock的最大价值也是最常用的,指定返回值可以用来伪造一个假的返回值,从而绕过对于真实对象的调用。如果真实对象的调用很复杂,入参或者调用条件很苛刻,那么直接用mock的指定返回功能绕过即可,这是很有价值的。
注意:
mock只是生成了一个壳子,不是真的创建了一个对象,无法进行状态的维护,需要对每个行为对应的属性都要进行自定义,如以下代码即使调用了set方法,也不会为属性赋值,属性仍然为null。
@Test
public void test(){
Person mockPerson=Mockito.mock(Person.class);
mockPerson.setName("bugMan");
assert mockPerson.getName()==null:"name属性值为空";
}
2.3.注解
除了编码的方式外,还提供了注解方式进行使用,从而使代码变得更加简洁。
2.3.1.@Mock
@Mock和Mockito.mock()功能相同。
@Mock
HashMap<String, Integer> mockHashMap;
@Test
public void saveTest()
{
//输入
mockHashMap.put("A", 1);
//期望
Mockito.verify(mockHashMap).put("A", 1);
assert mockHashMap.size()==0;
}
2.3.2.@Spy
@Spy和@Mock不同的是@Mock创建的是个壳子,而@Spy创建的真的是个对象,可以进行状态维护。
@Spy
HashMap<String, String> hashMap;
@Test
public void saveTest()
{
//输入
hashMap.put("name", "bugMan");
//期望
Mockito.verify(hashMap).put("name", "bugMan");
assert hashMap.size()==1;
}
2.3.3.@Captor
@Captor注释用于创建ArgumentCaptor对象,该类型的对象可以用来捕获参数。
@Mock
HashMap<String, String> hashMap;
@Captor
ArgumentCaptor<String> keyCaptor;
@Captor
ArgumentCaptor<String> valueCaptor;
@Test
public void saveTest()
{
hashMap.put("name", "bugMan");
Mockito.verify(hashMap).put(keyCaptor.capture(), valueCaptor.capture());
assert "name".equals(keyCaptor.getValue());
assert "bugMan".equals(valueCaptor.getValue());
}
2.3.4.@InjectMocks
@InjectMocks用来进行@Mock的注入,目的就是去掉手动注入,让代码变得简洁。
以一个service层注入dao层的操作为例:
dao层:
@Repository
public class MyRepository {
public void doSomething() {
System.out.println("here's dosomething");
}
public Model findById(Long id) {
return new Model(id, "Real Repository");
}
}
service层:
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
public void doSomething() {
this.myRepository.doSomething();
}
public Model findById(Long id) {
return this.myRepository.findById(id);
}
}
没有@InjectMocks的话,需要手动注入:
MyRepository myRepository = Mockito.mock(MyRepository.class);
MyService myService = new MyService(myRepository);
有@InjectMocks的话直接声明即可,@Mock注解的对象会自动注入进@InjectMocks注解的对象:
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService;
@Test
public void testInjectMocks() {
System.out.println(myService.getMyRepository().getClass());
}