mock框架有很多,这里去学习了mockito框架在日常开发中的使用以及一些使用注意事项
简单使用
1.stub打桩测试,通过触发定义好的stub描述条件,返回需要我们的行为
2.spy 和 mock的区别
1.mock是针对类或接口,生成对应的代理对象。 如下述List接口 2.spy是基于真实对象来生成对应新代理对象 如下述是真实的ArrayList对象
但用mock居多
3.每个单元测试最好断言 assert 也很方便
package com.zhanglijun.demo.zanbootdemo.util;
import com.google.common.collect.Lists;
import java.util.List;
import org.junit.Test;
import org.mockito.Mockito;
/**
* @author 夸克
* @create 2018/6/30 15:55
*/
public class MockitoTest {
/**
* 简单的stub (打桩测试)
* 触发了stubd的桩点 返回我们需要的行为
*/
@Test
public void testStub() {
String zero = "zero";
// 创建 mock 对象
List mock = Mockito.mock(List.class);
// when 描述触发条件 thenReturn 描述触发结果
Mockito.when(mock.get(0)).thenReturn(zero);
assert zero.equals(mock.get(0));
}
/**
* 使用回调进行打桩
*/
@Test
public void testCallbackStub() {
final String zero = "zero";
List mockList = Mockito.mock(List.class);
// invocation可以通过反射 回调接口
Mockito.when(mockList.get(0)).thenAnswer(invocation -> zero);
assert zero.equals(mockList.get(0));
}
/**
* 通过spy对真实对象进行stub 打桩测试
* 区分mock 和 spy :
* 1.mock是针对类或接口,生成对应的代理对象。 如上述List接口
* spy是基于真实对象来生成对应新代理对象 如下述是真实的ArrayList对象
*
* 2.使用最多的是用 mock 方式进行stub
*/
@Test
public void testSpyStub() {
List<String> list = Lists.newArrayList();
list.add("first");
list.add("second");
// 根据list真实对象 生成的spy对象
List<String> spy = Mockito.spy(list);
// 描述 spy的get(0)的触发行为 和 触发结果
Mockito.when(spy.get(0)).thenReturn("mock");
assert "mock".equals(spy.get(0));
}
}
容器管理
1.在开发过程中,我们都是需要对spring容器内bean进行测试,这里mockito 提供了一些注解去支持容器的管理。
2.
mockito 提供几个注解 配合spring容器完成Mock对象的初始化和依赖管理 * @InjectMocks 修饰的是由Spring容器管理注入的真实对象 是需要被依赖注入的对象 * @Mock 需要被mock的添加改注解 需要被依赖注入的对象添加 @InjectMocks * @Spy * 这些注解使用时,需要在方法执行之前调用注解初始化工作 MockitoAnnotations.initMocks(this) 使用@Before注解初始化工作
3. 几个注意点:
(1)@InjectMock 是要注入真正要生成bean的类,这里也可以像写代码接口注入方式一样去用@InjectMock注入接口,但是要加@Resource 或 @Autowire注解
(2)可以在一个UT中在初始化注解方法中用 given 和 willReturn去描述条件。 given如果要使用要引入static静态包。
import org.mockito.MockitoAnnotations;
package com.zhanglijun.demo.zanbootdemo.util;
import static org.mockito.BDDMockito.given;
import com.zhanglijun.demo.zanbootdemo.BaseTest;
import com.zhanglijun.demo.zanbootdemo.domain.mockito.UserMapper;
import com.zhanglijun.demo.zanbootdemo.domain.mockito.UserService;
import javax.annotation.Resource;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
/**
* mockito 测试 容器管理
* @author 夸克
* @create 2018/6/30 16:46
*/
public class MockitoUtilTest extends BaseTest{
/**
* mockito 提供几个注解 配合spring容器完成Mock对象的初始化和依赖管理
* @InjectMocks 修饰的是由Spring容器管理注入的真实对象 是需要被依赖注入的对象
* @Mock 需要被mock的添加改注解 需要被依赖注入的对象添加 @InjectMocks
* @Spy
* 这些注解使用时,需要在方法执行之前调用注解初始化工作 MockitoAnnotations.initMocks(this) 使用@Before注解初始化工作
*/
@Resource
@InjectMocks // 这里应该是具体spring 管理的 bean 如果有@Resource注解 可以用接口注入 否则必须用带@Service注解的bean去注入
private UserService userService;
// 需要mock的接口或者类 这里应该是接口
@Mock
private UserMapper userMapper;
/**
* 使用mockito注解要初始化
* 并且在这个初始化方法中可以 用 given 和 willReturn去mock一些数据
*/
@Before
public void before() {
MockitoAnnotations.initMocks(this);
/**
* given 和 willReturn 去 mock userMapper的方法数据
*
* 使用given 和 使用assertj一样 要引入static 包
*/
// given(userMapper.countById(Mockito.any())).willReturn(1);
}
@Test
public void testInjectionMockito() {
// 使用when 和 thenReturn 进行 打桩stub测试
Mockito.when(userMapper.countById(Mockito.any())).thenReturn(1);
Integer integer = userService.countById(2322l);
assert integer.equals(1);
}
}
两个模拟的userService 和 userMapper类
package com.zhanglijun.demo.zanbootdemo.domain.mockito;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
/**
* @author 夸克
* @create 2018/6/30 17:15
*/
@Service
public class UserServiceImpl implements UserService{
@Resource
private UserMapper userMapper;
@Override
public Integer countById(Long id) {
return userMapper.countById(id);
}
}
package com.zhanglijun.demo.zanbootdemo.domain.mockito;
import org.springframework.stereotype.Component;
/**
* @author 夸克
* @create 2018/6/30 17:17
*/
@Component
public class UserMapperImpl implements UserMapper{
@Override
public Integer countById(Long id) {
return 222;
}
}