JUnit和Mockito
对于JUnit,这里就不详细介绍了,网上的教程有很多,比如这个和这个。
下面主要介绍一下Mockito。
什么是mock测试,什么是mock对象?
先来看看下面这个示例:

从上图可以看出如果我们要对A进行测试,那么就要先把整个依赖树构建出来,也就是BCDE的实例。
一种替代方案就是使用mocks

从图中可以清晰的看出:
- mock对象就是在调试期间用来作为真实对象的替代品
- mock测试就是在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试
模拟的好处是什么?
-
提前创建测试; TDD(测试驱动开发)
如果你创建了一个Mock那么你就可以在service接口创建之前写Service Tests了,这样你就能在开发过程中把测试添加到你的自动化测试环境中了。换句话说,模拟使你能够使用测试驱动开发。 -
团队可以并行工作
这类似于上面的那点;为不存在的代码创建测试。但前面讲的是开发人员编写测试程序,这里说的是测试团队来创建。当还没有任何东西要测的时候测试团队如何来创建测试呢?模拟并针对模拟测试!这意味着当service借口需要测试时,实际上QA团队已经有了一套完整的测试组件;没有出现一个团队等待另一个团队完成的情况。这使得模拟的效益型尤为突出了。 -
你可以创建一个验证或者演示程序。
-
为无法访问的资源编写测试
这个好处不属于实际效益的一种,而是作为一个必要时的“救生圈”。有没有遇到这样的情况?当你想要测试一个service接口,但service需要经过防火墙访问,防火墙不能为你打开或者你需要认证才能访问。遇到这样情况时,你可以在你能访问的地方使用MockService替代,这就是一个“救生圈”功能。
-
Mock 可以分发给用户
-
隔离系统
知道什么是mock测试后,那么我们就来认识一下mock框架---Mockito。
Mockito区别于其他模拟框架的地方主要是允许开发者在没有建立“预期”时验证被测系统的行为。
Mockito相关教程:
(与此同时推荐一个东西,SpringOckito, 不过已经2年没更新了。)
mockito入门实例
Maven依赖:
XML 代码
<dependencies>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
</dependencies>
首先,需要在@Before注解的setUp()中进行初始化(下面这个是个测试类的基类)
Java代码
public abstract class MockitoBasedTest {
@Before
public void setUp() throws Exception {
// 初始化测试用例类中由Mockito的注解标注的所有模拟对象
MockitoAnnotations.initMocks(this);
}
}
Java代码
import static org.mockito.Mockito.*;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
public class SimpleTest {
@Test
public void simpleTest(){
//创建mock对象,参数可以是类,也可以是接口
List<String> list = mock(List.class);
//设置方法的预期返回值
when(list.get(0)).thenReturn("helloworld");
String result = list.get(0);
//验证方法调用(是否调用了get(0))
verify(list).get(0);
//junit测试
Assert.assertEquals("helloworld", result);
}
}
创建mock对象不能对final,Anonymous ,primitive类进行mock。
可对方法设定返回异常
Java代码
when(list.get(1)).thenThrow(new RuntimeException("test excpetion"));
stubbing另一种语法(设置预期值的方法),可读性不如前者
Java代码
doReturn("secondhello").when(list).get(1);
没有返回值的void方法与其设定(支持迭代风格,第一次调用donothing,第二次dothrow抛出runtime异常)
Java代码
doNothing().doThrow(new RuntimeException("void exception")).when(list).clear();
list.clear();
list.clear();
verify(list,times(2)).clear();
参数匹配器(Argument Matcher)
Matchers类内加你有很多参数匹配器 anyInt、anyString、anyMap.....Mockito类继承于Matchers,Stubbing时使用内建参数匹配器,下例:
Java代码
@Test
public void argumentMatcherTest(){
List<String> list = mock(List.class);
when(list.get(anyInt())).thenReturn("hello","world");
String result = list.get(0)+list.get(1);
verify(list,times(2)).get(anyInt());
Assert.assertEquals("helloworld", result);
}
需要注意的是:如果使用参数匹配器,那么所有的参数都要使用参数匹配器,不管是stubbing还是verify的时候都一样。
网友评论