Mockito教程(单测mock)
1 Mockito 介绍 [3]
1.1 Mockito是什么?
Mockito是mocking框架,它让你用简洁的API做测试。而且Mockito简单易学,它可读性强和验证语法简洁。
1.2 为什么需要Mock
测试驱动的开发( TDD)要求我们先写单元测试,再写实现代码。在写单元测试的过程中,我们往往会遇到要测试的类有很多依赖,这些依赖的类/对象/资源又有别的依赖,从而形成一个大的依赖树,要在单元测试的环境中完整地构建这样的依赖,是一件很困难的事情。如下图所示:
为了测试类A,我们需要Mock B类和C类(用虚拟对象来代替)如下图所示:
1.3 Stub和Mock异同[1]
- 相同:Stub和Mock都是模拟外部依赖
- 不同:Stub是完全模拟一个外部依赖, 而Mock还可以用来判断测试通过还是失败
在软件测试中,"Stub"(桩)和"Mock"(模拟)都是用来替代或模仿实际组件的测试工具,用于隔离被测系统的一部分,从而可以专注于测试某一个具体的模块。尽管它们有相似的目的,但在使用方式和功能上有一些关键区别:
1. **Stub(桩)**:
- Stub是一种简单的替代对象,通常用于模拟复杂的系统或外部服务。它提供固定的响应或行为,这些响应或行为是预先定义好的,不需要根据输入动态变化。
- Stub主要用于控制测试环境,在测试过程中提供一致性和可预测性。
- 它们通常比较简单,可能只是简单地返回一个预设的数据集或者执行一个预定义的操作。
- Stub常用于当一个组件需要与数据库或其他外部系统交互时,但测试时并不关心这些系统的具体实现细节。
2. **Mock(模拟)**:
- Mock对象比Stub更复杂,它不仅可以模拟对象的行为,还可以记录和验证方法调用的次数以及顺序。
- Mock允许你在测试时指定期望的方法调用,并检查这些调用是否按预期发生。如果方法没有按照预期的方式被调用,Mock可能会抛出异常或失败。
- Mock也可以设置预期的返回值,甚至可以根据传入的不同参数返回不同的结果。
- 使用Mock时,你可以更精细地控制测试条件,并且能够验证代码中的逻辑是否正确地处理了各种情况。
总结来说,Stub主要用于提供静态的或固定的行为,而Mock则更多地用于验证对象之间的交互是否符合预期。在实际开发中,根据测试的具体需求选择合适的工具是非常重要的。
2 使用Mockito [2][4]
2.1 验证行为
1 @Test 2 public void verify_behaviour(){ 3 //模拟创建一个List对象 4 List mock = mock(List.class); 5 //使用mock的对象 6 mock.add(1); 7 mock.clear(); 8 //验证add(1)和clear()行为是否发生 9 verify(mock).add(1); 10 verify(mock).clear(); 11 }
2.2 模拟我们所期望的结果
@Test public void when_thenReturn(){ //mock一个Iterator类 Iterator iterator = mock(Iterator.class); //预设当iterator调用next()时第一次返回hello,第n次都返回world when(iterator.next()).thenReturn("hello").thenReturn("world"); //使用mock的对象 String result = iterator.next() + " " + iterator.next() + " " + iterator.next(); //验证结果 assertEquals("hello world world",result); }
1 @Test(expected = IOException.class) 2 public void when_thenThrow() throws IOException { 3 OutputStream outputStream = mock(OutputStream.class); 4 OutputStreamWriter writer = new OutputStreamWriter(outputStream); 5 //预设当流关闭时抛出异常 6 doThrow(new IOException()).when(outputStream).close(); 7 outputStream.close(); 8 }