一、Mockito 概念图
image.png二、 前要知识
1、测试的类型
- Unit test : 单元测试是关注单一的类,检查这个类中的代码是否按预期正确执行
- Integration test:检查开发的模块和其它模块整合时是否正确执行
- End-to-End test:将整个系统作为一个整体,然后从用户的角度去进行测试,看系统在实际应用中是否正确执行
2、单元测试概念
- 被测系统(System under test,SUT):被测系统是当前被测试的系统,目的是检查当前被测的系统是否被正确运行,根据测试系统的不同,SUT 所指代的内容也不同,可以是一个类也可以是整个系统。
- 测试依赖组件(DOC):被测系统所依赖的组件,例如:进行 UserService 的单元测试时,UserService 会依赖 UserDao ,那么 UserDao 就是 DOC
- 测试替身(Test Double):用一些功能简单的且其行为和实际对象类似的假对象来作为 SUT 的依赖对象
- Test stub:为 SUT 提供假数据的对象
- Fake object:实现了简单功能的一个假对象
- Mock object:用来模拟实际的对象,并校验当前的 mock object 的方法是否符合预期
- Dummy object:在测试中并不使用,但是为了测试代码正常的编译/运行而添加的对象(比如仅仅填充参数列表)
- Test spy:包装一个真实的 Java 对象,并返回一个包装后的新对象,对这个新对象的所有方法进行调用时,都会委派为实际的对象。
三、Mockito、PowerMockito
首先引入maven依赖
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.23.0</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
指定执行方式
@RunWith(PowerMockRunner.class)
指定需要被mock的静态类
@PrepareForTest({ LoginUtil.class })
mock方法
//mock静态类
PowerMockito.mockStatic(LoginUtil.class);
//mock带返回值的方法
PowerMockito.when(LoginUtil.getUser()).thenReturn(new LoginUser());
//mock没有返回值(void)的方法
doNothing().when(bookService).deleteBookById(Mockito.any(),Mockito.any());
//mock调用方法抛出异常
doThrow(new RuntimeException()).when(bookService).addBook(Mockito.any(),Mockito.any());
在测试类中,只要将待测的类标注为@InjectMocks,将其依赖的其他类标注为 @Mock,就可以使用MockitoAnnotations.initMocks(this);这句话自动将依赖的类注入待测类,如果依赖类在spring的管理下有自己的name,那么甚至在待测类中都不需要写setter方法。
@InjectMocks
BookServiceImpl bookService;
@Mock
BookDaoImpl bookDao;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
//这句话执行以后,bookDao等bookService依赖的bean会自动注入到abcService中。
}
完整的测试类,上面说的不明白的可以参考下面的代码:
1、待测类
@Service
public class AbcService {
@Autowired
private AaaDao aaaDao;
@Autowired
private BbbDao bbbDao;
......//注:此处省略的代码中并不包含aaaDao和bbbDao的setter方法。
}
2、测试类
//使用这个跑单测,所有目标类调用的服务都需要mock,不会加载容器支持静态方法mock
@RunWith(PowerMockRunner.class)
//如果有调用其他类中的静态方法,则需要指定被mock的静态资源类,没有的话则不需要
//@PrepareForTest({ LoginUtil.class })
public class AbcServiceTest{
@InjectMocks
AbcService abcService;
@Mock
AaaDao aaaDao;
@Mock
BbbDao bbbDao;
@Before
public void setup(){
MockitoAnnotations.initMocks(this);//这句话执行以后,aaaDao和bbbDao自动注入到abcService中。
//在这之后,你就可以放心大胆地使用when().then()、
//Mockito.doNothing().when(obj).someMethod()、
//doThrow(new RuntimeException()).when(obj).someMethod(Mockito.any());
//等进行更详细的设置。
}
@Test
public void addAbc() {
when(aaaDao.addAbc()).thenReturn(ABCDO);
when(bbbDao.addAbc(Mockito.any(),Mockito.any())).thenReturn(1);
PojoResult pojoResult = abcService.addAbc(AbcVo);
//最后这里加上断言,进行判断执行结果是否达到我们的预期
TestCase.assertEquals(true,pojoResult.getContent());
}
}
网友评论