c,判断你要得到什么样的结果,也就是你的函数要改变哪些变量的值,然后在UT的最后用Assert断言来对这些期望值进行预测判断
下面写一个例子,本例要验证fillModel这个函数,它的作用是将一个List
本例中输入参数是一个List
本例需要依赖itemService下的getSpuMap方法,希望这个方法返回一个map,而这个map中value元素model2的defined属性经过这个方法被设置为true,注意这个方法不是我们写的,所以在这里需要被mock掉,而mock掉后返回的结果是希望含有defined属性为true的。
所以,首先我们构造一个这个itemService方法的返回值,也就是一个map,这个map的value是一个model2类,而model2的defined被我们预先设置为true;
然后用when语句mock掉itemService方法,使其返回我们构造好的这个map:
when(itemService.getSpuMap(anyLong(), anyList())).thenReturn(map);
最后调用我们要测验的方法,然后查看调用后model的defined是否和我们预设的model2的值一样。
需要注意的是,因为我们要测试的fillModel这个方法是需要被实际执行的,不能被mock,所以这个方法的类(通常也就是你的测试类对应的方法类)需要加上@InjectMock注解。而其中依赖的itemService.getSpuMap方法不是我们写的,我们只是依赖于它的返回值,这个类的初始化要加上@Mock注解。
@Test
public void test_fillModel(){
//参数准备
Long kdtId = 100L;
Long id = 10002L;
Model model = new Model();
model.setKdtId(kdtId);
model.setId(id);
List models = Lists.newArrayList(model);
//做好预期的结果
Map map = new HashMap<>();
Model2 model2 = new Model2();
model2.setItemId(id);
model2.setKdtId(kdtId);
model2.setDefined(true);
spuMap.put(10002L,model2);
//通过when语句mock出fillHasMultiSku函数中所依赖的getSpuMap资源,该资源输入任意参数,得到之前做好的预期结果spyMap
when(itemService.getSpuMap(anyLong(), anyList())).thenReturn(map);
//实际执行fillHasMultiSku函数,models中填入信息
itemListInnerService.fillModel(models);
Assert.assertEquals(models.get(0).isDefined(),itemSkuTotalModel.isDefined());
}
另外还有很多实用Mockito进行测试的小问题,举几个例子:
1,巧用verify语句
verify是用来验证某函数的执行与否,执行几次,没有被执行等
@Test
public void verifying_number_of_invocations(){
List list = mock(List.class);
list.add(1);
list.add(2);
list.add(2);
list.add(3);
list.add(3);
list.add(3);
//验证是否被调用一次,等效于下面的times(1)
verify(list).add(1);
verify(list,times(1)).add(1);
//验证是否被调用2次
verify(list,times(2)).add(2);
//验证是否被调用3次
verify(list,times(3)).add(3);
//验证是否从未被调用过
verify(list,never()).add(4);
//验证至少调用一次
verify(list,atLeastOnce()).add(1);
//验证至少调用2次
verify(list,atLeast(2)).add(2);
//验证至多调用3次
verify(list,atMost(3)).add(3);
2,用doThrow验证抛出异常
@Test(expected = RuntimeException.class)
public void doThrow_when(){
List list = mock(List.class);
doThrow(new RuntimeException()).when(list).add(1);
list.add(1);
}
3,用spy来真正调用真实的api
@Test
public void real_partial_mock(){
//通过spy来调用真实的api
List list = spy(new ArrayList());
assertEquals(0,list.size());
A a = mock(A.class);
//通过thenCallRealMethod来调用真实的api
when(a.doSomething(anyInt())).thenCallRealMethod();
assertEquals(999,a.doSomething(999));
}
class A{
public int doSomething(int i){
return i;
}
}
4,使用 new Answer()来对未预设的调用更改默认期望值
@Test
public void unstubbed_invocations(){
//mock对象使用Answer来对未预设的调用返回默认期望值
List mock = mock(List.class,new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return 999;
}
});
//下面的get(1)没有预设,通常情况下会返回NULL,但是使用了Answer改变了默认期望值
assertEquals(999, mock.get(1));
//下面的size()没有预设,通常情况下会返回0,但是使用了Answer改变了默认期望值
assertEquals(999,mock.size());
}
Mock的使用相对简单,但是有很多小细节需要注意,以后使用过程中遇到的问题会更在后面。