Android Studio 单元测试与模拟测试详解

本文详细解析Android Studio中的单元测试和模拟测试。通过单元测试确保代码模块独立运行的正确性,利用模拟测试在无依赖环境下进行应用功能验证。
摘要由CSDN通过智能技术生成

测试的分类

单元测试

位于:module-name/src/test/java/.
这些测试运行在本地JVM和没有访问Android框架api功能

设置环境:
您还需要为您的项目配置测试依赖使用标准api提供的JUnit 4的框架。如果您的测试需要与Android依赖关系,包括
当地Mockito(详解见文章的下面内容)库来简化你的单元测试。
在你的应用程序的顶层。gradle文件时,您需要指定这些库的依赖关系:
dependencies {
// Required -- JUnit 4 framework
testCompile 'junit:junit:4.12'(这个创建工程的时候已经存在)
// Optional -- Mockito framework
testCompile 'org.mockito:mockito-core:1.10.19'
}

测试例子:(方法名字不用test开头)
方法名可以采用一种格式,如: [测试的方法]_[测试的条件]_[符合预期的结果]
public class AddTest {
    @Test
    public void add() {
        assertEquals(new MainActivity().add(2,3),5);
    }
}

Mockito详解:
1、验证行为

@Test  
public void verify_behaviour(){  
    //模拟创建一个List对象  
    List mock = mock(List.class);  
    //使用mock的对象  
    mock.add(1);  
    mock.clear();  
    //验证add(1)和clear()行为是否发生  
    verify(mock).add(1);  
    verify(mock).clear();  
}  

2、模拟我们所期望的结果
@Test  
public void when_thenReturn(){  
    //mock一个Iterator类  
    Iterator iterator = mock(Iterator.class);  
    //预设当iterator调用next()时第一次返回hello,第n次都返回world  
    when(iterator.next()).thenReturn("hello").thenReturn("world");  
    //使用mock的对象  
    String result = iterator.next() + " " + iterator.next() + " " + iterator.next();  
    //验证结果  
    assertEquals("hello world world",result);  
}  

@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();  
}  

3、参数匹配
@Test  
public void with_arguments(){  
    Comparable comparable = mock(Comparable.class);  
    //预设根据不同的参数返回不同的结果  
    when(comparable.compareTo("Test")).thenReturn(1);  
    when(comparable.compareTo("Omg")).thenReturn(2);  
    assertEquals(1, comparable.compareTo("Test"));  
    assertEquals(2, comparable.compareTo("Omg"));  
    //对于没有预设的情况会返回默认值  
    assertEquals(0, comparable.compareTo("Not stub"));  
}  
除了匹配制定参数外,还可以匹配自己想要的任意参数
@Test  
public void with_unspecified_arguments(){  
    List list = mock(List.class);  
    //匹配任意参数  
    when(list.get(anyInt())).thenReturn(1);  
    when(list.contains(argThat(new IsValid()))).thenReturn(true);  
    assertEquals(1, list.get(1));  
    assertEquals(1, list.get(999));  
    assertTrue(list.contains(1));  
    assertTrue(!list.contains(3));  
}  

private class IsValid extends ArgumentMatcher<List>{  
    @Override  
    public boolean matches(Object o) {  
        return o == 1 || o == 2;  
    }  
}  
需要注意的是如果你使用了参数匹配,那么所有的参数都必须通过matchers来匹配
@Test  
public void all_arguments_provided_by_matchers(){  
    Comparator comparator = mock(Comparator.class);  
    comparator.compare("nihao","hello");  
    //如果你使用了参数匹配,那么所有的参数都必须通过matchers来匹配  
    verify(comparator).compare(anyString(),eq("hello"));  
    //下面的为无效的参数匹配使用  
    //verify(comparator).compare(anyString(),"hello");  
}  
4、验证确切的调用次数
@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);  
}  
5、模拟方法体抛出异常
@Test(expected = RuntimeException.class)  
public void doThrow_when(){  
    List list = mock(List.class);  
    doThrow(new RuntimeException()).when(list).add(1);  
    list.add(1);  
}  
6、验证执行顺序
@Test  
public void verification_in_order(){  
    List list = mock(List.class);  
    List list2 = mock(List.class);  
    list.add(1);  
    list2.add("hello");  
    list.add(2);  
    list2.add("world");  
    //将需要排序的mock对象放入InOrder  
    InOrder inOrder = inOrder(list,list2);  
    //下面的代码不能颠倒顺序,验证执行顺序  
    inOrder.verify(list).add(1);  
    inOrder.verify(list2).add("hello");  
    inOrder.verify(list).add(2);  
    inOrder.verify(list2).add("world");  
}  
7、确保模拟对象上无互动发生
@Test  
public void verify_interaction(){  
    List list = mock(List.class);  
    List list2 = mock(List.class);  
    List list3 = mock(List.class);  
    list.add(1);  
    verify(list).add(1);  
    verify(list,never()).add(2);  
    //验证零互动行为  
    verifyZeroInteractions(list2,list3);  
}  
8、找出冗余的互动(即未被验证到的)
@Test(expected = NoInteractionsWanted.class)  
public void find_redundant_interaction(){  
    List list = mock(List.class);  
    list.add(1);  
    list.add(2);  
    verify(list,times(2)).add(anyInt());  
    //检查是否有未被验证的互动行为,因为add(1)和add(2)都会被上面的anyInt()验证到,所以下面的代码会通过  
    verifyNoMoreInteractions(list);  

    List list2 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值