1概述
Mickito模拟器是主流的单元测试框架之一,它需要与Junit测试框架一起使用.
2.相关概念
2.1存根类(Stub)
存根(Stub)类是实现了一个接口或者抽象类的类,可以在测试过程中可以使用该类对象调用该类的方法进行测试.存根类的对象需要手动创建.如:
Private PingAnEnterService pingAnEnterService = new PingAnEnterServiceImpl();
2.2模拟对象 (Mock)
模拟对象(mock object)是一个接口或者类的虚拟实现.可以使用mock(T.class)方法或使用@Mock注解生成模拟对象.如:
//模拟创建一个List对象
List mock = mock(List.class);
或
@Mock
private List<String,Object> list;
存根和模拟对象都可以传递给其他的对象进行测试。你的一些单元测试可以测这些类的正确性等。利用存根对象或者模拟对象可以保证测试过程中不受到其他的影响
3.对应的注解
3.1 @Mock
生成一个模拟对象.与方法mock(T t)作用一样.有个name属性,可以设置对象的别名.
3.2 @InjectMocks
创建一个实例,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中.
注意:必须使用@RunWith(MockitoJUnitRunner.class) 或 Mockito.initMocks(this)进行mocks的初始化和注入。如下:
方式一:
@RunWith(MockitoJUnitRunner.class)
public class Test{
@InjectMocks //创建someHandler实例
private SomeHandler someHandler;
@Mock
private OneDependency oneDependency; // 此mock将被注入到someHandler
}
方式二:
public class Test{
@InjectMocks
//创建someHandler实例. SomeHandler是类
//private SomeHandler someHandler;
//创建someHandler实例. SomeHandler是接口
private SomeHandler someHandler = new SomeHandlerImpl();
@Mock
private OneDependency oneDependency; // 此mock将被注入到someHandler
@Before
public void before(){
MockitoAnnotations.initMocks(this);
//给模拟对象属性赋值
when(oneDependency.setOpenId).thenReturn(“mlsama”);
. . .
}
}
4.Mockito的限制
以下的类型不能进行构造:
终态类(final classes)
匿名类(anonymous classes)
基本数据类型(primitive types)
5.模拟对象的配置
其实就是对使用@Mock或mock(T t)创建的模拟对象方法设置返回值(通过set方法完成成员变量赋值).
5.1方式一
设置返回值:
when(mock.method()).thenReturn(value)
设置返回异常:
when(mock.method()).thenThrow(new XXXException())
迭代风格: 第一次调用返回,第二次返回
when(mock.method()).thenReturn("Hello").thenReturn("World")
例如:
@Test
public void mock1(){
//模拟创建一个List对象
List mock = mock(List.class);
//这里也可以: thenReturn (new RuntimeException());
when(mock.get(1)).thenReturn(1);
when(mock.get(1)).thenThrow(newRuntimeException());
System.out.println(mock.get(1));//抛异常
}
需要注意的是: when(T t),所以里面的方法的返回值不能是void
5.2方式二
设置返回值:
doReturn(value).when(mock) .method()
设置返回异常:
doThrow(new XXXException()).when(mock) .method()
例如:
@Test
public void mock1(){
//模拟创建一个List对象
List mock =mock(List.class);
doReturn(1), when(mock) .get(1);
doThrow(new RuntimeException()).when(mock) .get(1);
System.out.println(mock.get(1));//抛异常
}
注意:以上方式不支持返回值为void的方法.
5.3对void方法进行方法预期设定
doNothing() 模拟不做任何返回(mock对象void方法的默认返回)
doNothing().when(mock).remove();
doThrow(Throwable) 模拟返回异常
doThrow(new RuntimeException()).when(mock).remove();
6.验证模拟对象的行为
Mockito 跟踪了所有的方法调用和参数的调用情况。verify()可以验证方法的行为。
格式:
verify(模拟对象).模拟对象的方法( 参数列表 )
查看下面的例子:
@Test
public void testMap() {
Map mock =Mockito.mock( Map.class );
Mockito.when(mock.get( "city" ) ).thenReturn( "深圳" );
// test code
assertEquals("城市测试", "深圳", mock.get( "city" ) );
Mockito.verify(mock).get( Matchers.eq( "city" ) );
Mockito.verify(mock, Mockito.times( 2 ) );
}
7. Spy
@Spy 或者方法 spy() 可以包含一个真实的对象. 每次调用,除非特出指定,否则委托给该真实对象的调用.
@Test
public void testSpy() {
// Lets mock aLinkedList
List list = new LinkedList();
list.add("yes" );
List spy =Mockito.spy(list);
//You have to usedoReturn() for stubbing
assertEquals("yes", spy.get( 0 ) );
Mockito.doReturn("foo").when(spy).get(0);
assertEquals("foo", spy.get( 0 ) );
}