单元测试的思路是在不涉及依赖的状况下测试代码,通常是测试service层的方法,但实际的代码常会涉及到依赖,一个可行的方法就是使用模拟对象来替换依赖对象。框架
Mockito 是一个流行 mock 框架,能够和JUnit结合起来使用。Mockito 容许你建立和配置 mock 对象。使用Mockito能够明显的简化对外部依赖的测试类的开发。maven
通常使用 Mockito 须要执行下面三步函数
模拟并替换测试代码中外部依赖。单元测试
执行测试代码测试
验证测试代码是否被正确的执行this
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <scope>test</scope> </dependency>
若是在代码中静态引用了org.mockito.Mockito.*;
,那你你就能够直接调用静态方法和静态变量而不用建立对象,譬如直接调用 mock() 方法。spa
Mockito 还支持经过 @Mock
注解的方式来建立 mock 对象.net
使用注解,那么必需要实例化 mock 对象。Mockito 在遇到使用注解的字段的时候,会调用 MockitoAnnotations.initMocks(this)
来初始化该 mock 对象。另外也能够经过使用@RunWith(MockitoJUnitRunner.class)
来达到相同的效果。code
注解对象
调用方法:
when(….).thenReturn(….)能够被用来定义当条件知足时函数的返回值,若是你须要定义多个返回值,能够屡次定义。当你屡次调用函数的时候,Mockito 会根据你定义的前后顺序来返回返回值。Mocks 还能够根据传入参数的不一样来定义不一样的返回值。譬如说你的函数能够将anyString 或者 anyInt做为输入参数,而后定义其特定的放回值。
自定义方法的返回值
Mockito.when(方法).thenReturn(返回值)
Mockito.when(方法).thenReturn(返回值1).thenReturn(返回值2)
无返回值
对于无返回值的函数,咱们可使用doReturn(…).when(…).methodCall来得到相似的效果。例如咱们想在调用某些无返回值函数的时候抛出异常,那么可使用doThrow 方法。
以下所示:
Mockito.doThrow(new IOException()).when(mockStream).close()
仅调用方法,但啥也不作
Mockito.doNothing().when(tagRepository).deleteByTagId(1)
注:tagRepository有一个方法是 deleteByTagId(int tagId)
验证 query 方法是否被 MyDatabase 的 mock 对象调用
verify(databaseMock).query("* from t");
查看在传入参数为12的时候方法是否被调用
verify(test).testing(Matchers.eq(12));
方法是否被调用两次
verify(test, times(2)).getUniqueId();
verify(mock, never()).someMethod("never called");
verify(mock, atLeastOnce()).someMethod("called at least once");
verify(mock, atLeast(2)).someMethod("called at least twice");
verify(mock, times(5)).someMethod("called five times");
verify(mock, atMost(3)).someMethod("called at most 3 times");
下面三种数据类型则不可以被测试
final classes
anonymous classes
primitive types
Mockito 不可以 mock 静态方法,所以咱们可使用 Powermock
powerMock能mock静态、final、私有方法等
PowerMock支持EasyMock和Mockito。
@RunWith(PowerMockRunner.class)
@PrepareForTest( { YourClassWithEgStaticMethod.class })
若是测试用例里没有使用注解@PrepareForTest,那么能够不用加注解@RunWith(PowerMockRunner.class),反之亦然。当你须要使用PowerMock强大功能(Mock静态、final、私有方法等)的时候,就须要加注解@PrepareForTest。
详见 http://blog.csdn.net/knighttools/article/details/44630975
PowerMockito.when(file.exists()).thenReturn(true);
File file = PowerMockito.mock(File.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.whenNew(File.class).withArguments("bbb").thenReturn(file);
PowerMockito.when(file.exists()).thenReturn(true);
ClassDependency depencency = PowerMockito.mock(ClassDependency.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.when(depencency.isAlive()).thenReturn(true);
PowerMockito.mockStatic(ClassDependency.class);
PowerMockito.when(ClassDependency.isExist()).thenReturn(true);
ClassUnderTest underTest = PowerMockito.mock(ClassUnderTest.class);
PowerMockito.when(underTest.callPrivateMethod()).thenCallRealMethod();
PowerMockito.when(underTest, "isExist").thenReturn(true);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("aaa")).thenReturn("bbb");
(1) 验证静态方法:
PowerMockito.verifyStatic();
Static.firstStaticMethod(param);
(2) 扩展验证:
PowerMockito.verifyStatic(Mockito.times(2)); // 被调用2次
Static.thirdStaticMethod(Mockito.anyInt()); // 以任何整数值被调用