使用Junit和mockito写单测的一些注意点
2018-03-10 15:22
381 查看
使用Mockito和junit进行单测的一些要点:1,总的来说写一个单测需要提前进行三件事a,看好你要测的函数的入参,构建出一个入参;b,详细看好你的函数中依赖了哪些写好的函数,这些函数需要进行@Mock声明,将他们mock掉,使得你的单测只测试你写的逻辑代码;c,判断你要得到什么样的结果,也就是你的函数要改变哪些变量的值,然后在UT的最后用Assert断言来对这些期望值进行预测判断下面写一个例子,本例要验证fillModel这个函数,它的作用是将一个List<Models>中每一个model的defined属性设置为true,需要调用外部的依赖itemService来获取一个model2的defined值,然后将这个值填入model的defined属性中。本例中输入参数是一个List<Models>,一个model里填入kdtId和id两个属性,所以首先进行参数准备(见代码);本例需要依赖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注解。
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
9966
()).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的使用相对简单,但是有很多小细节需要注意,以后使用过程中遇到的问题会更在后面。
@Test public void test_fillModel(){ //参数准备 Long kdtId = 100L; Long id = 10002L; Model model = new Model(); model.setKdtId(kdtId); model.setId(id); List<Model> models = Lists.newArrayList(model); //做好预期的结果 Map<Long, Model2> 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
9966
()).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的使用相对简单,但是有很多小细节需要注意,以后使用过程中遇到的问题会更在后面。
相关文章推荐
- 使用junit+mockito进行mock测试实例
- 单元测试及框架简介 --junit、jmock、mockito、powermock的简单使用
- 单元测试及框架简介 --junit、jmock、mockito、powermock的简单使用
- 使用Spring+Junit+Mockito做代码自测
- Mockito使用注意事项
- 基于JUnit使用PowerMock的Mockito扩展在Maven测试项目中的配置说明
- junit与testng 分别和mockito 结合使用例子
- Swift开发过程中常用到的一些使用技巧和注意的地方
- Zepto 使用中的一些注意点
- 使用 Elmah一些要注意的问题
- 使用cisco设备要注意的一些问题?
- php中使用include(require)嵌套包含文件时的一些注意问题
- Mybatis中使用junit的一些技巧
- 使用mex进行混合编程的一些注意事项
- 使用ObjectDataSource为ListView高效分页一些注意事项
- Mockito 简单使用
- EditText的一些使用注意点
- Hive SQL 使用时的注意事项和一些踩过的坑
- Python中使用装饰器时需要注意的一些问题
- 关于Android PopupWindow 使用要注意的一些地方