版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/xkzju2010/article/details/62455093
JUnit是单元测试框架,很棒的。
而Mockito是一种生成模拟对象——“假对象”工具。
一般是将两者结合起来进行测试。
官方例子是
List mock = mock( List.class );
when( mock.get(0) ).thenReturn( 1 );
assertEquals( "预期返回1", 1, mock.get( 0 ) );// mock.get(0) 返回 1
在maven项目中,先增加依赖。
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
当然会有junit的依赖
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
为了代码的简介,静态导入包
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
在示例代码中
@Test
public void test() {
List mock = mock(List.class);
mock.add(1);
mock.clear();
verify(mock).add(1);
verify(mock).clear();
// when(mock.get(0)).thenReturn(1);
// assertEquals("预期1",1,mock.get(0));
}
大致的意思就是进行add方法和clear方法的验证。
对返回规则的验证
@Test
public void whenThenReturn() {
// mock一个Iterator类
Iterator iterator = mock(Iterator.class);
// 假设iterator调用next()时,第一次返回hello,第n次返回world;
when(iterator.next()).thenReturn("hello").thenReturn("world");
// 使用mock的对象
String resString = iterator.next() + " " + iterator.next() + " "
+ iterator.next();
assertEquals("hello world world", resString);
}
如果没有返回值的,会用到doNothing()
doNothing().when(obj).notify();
// 或直接
when(obj).notify();
可以强制抛出异常,对异常捕捉进行test
@Test(expected = IOException.class)
public void when_thenThrow() throws IOException {
OutputStream outputStream = mock(OutputStream.class);
OutputStreamWriter writer = new OutputStreamWriter(outputStream);
// 预设当流关闭时,抛出异常
doThrow(new IOException()).when(outputStream).close();
outputStream.close();
}
上面,在调用outputStream的close方法时,抛出IO异常,对齐进行验证。
关注Verify
前面提到的 when(……).thenReturn(……) 属于状态测试,某些时候,测试不关心返回结果,而是侧重方法有否被正确的参数调用过,这时候就应该使用 验证方法了。从概念上讲,就是和状态测试所不同的“行为测试”了。
一旦使用 mock() 对模拟对象打桩,意味着 Mockito 会记录着这个模拟对象调用了什么方法,还有调用了多少次。最后由用户决定是否需要进行验证,即 verify() 方法。
正如前面所示的例子,可以校验调用的次数。
@Test
public void verify_test() {
Map mockmap = mock(Map.class);
when(mockmap.get("c")).thenReturn("杭州");
//关注参数是否有传入
verify(mockmap).get(Matchers.eq("c"));
//关注调用的次数
verify(mockmap,times(2));
}
Mockito除了times(N),还有以下几个
- never() 没有被调用,相当于 times(0)
- atLeast(N) 至少被调用 N 次
- atLeastOnce() 相当于 atLeast(1)
- atMost(N) 最多被调用 N 次
所谓 Mock 与 Stub 打桩,其实它们之间不能互为其表。但 Mockito 语境中则 Stub 和 Mock 对象同时使用的 。因为它既可以设置方法调用返回值,又可以验证方法的调用。有关 stub 和 mock 的详细论述请见 Martin Fowler 大叔的文章 《Mocks Aren't Stub》 。
下面不想整理了,参考
Spy的使用
意思就是可以修改真实对象的某些方法,不用更改他的基本行为特性,类似AOP。
List list = new LinkedList();
List spy = spy(list);
//optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);
//using the spy calls <b>real</b> methods
spy.add("one");
spy.add("two");
//prints "one" - the first element of a list
System.out.println(spy.get(0));
//size() method was stubbed - 100 is printed
System.out.println(spy.size());
//optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");
spy 保留了 list 的大部分功能,只是将它的 size() 方法改写了。
其他
可以在刚刚开始的时候,通过
@Before
的注解来进行前期的初始化工作。
public class ArticleManagerTest {
@Mock private ArticleCalculator calculator;
@Mock private ArticleDatabase database;
@Mock private UserProvider userProvider;
@Before public void setup() {
MockitoAnnotations.initMocks(testClass);
}
}
貌似 Mockito 的注解都比较强大,有待以后再看看:
《学习Mockito - Mockito对Annotation的支持》, http://jilen.iteye.com/blog/1427368
下面,有时间再整理。