引述:程序测试对保障应用程序正确 性而言,其重要性怎么样强调都不为过。JUnit是必须事先掌握的测试框架,大多数测试框架和测试工具都在此基础上扩展而来,Spring对测试所提供的 帮助类也是在JUnit的基础上进行演化的。直接使用JUnit测试基于Spring的应用存在诸多不便,不可避免地须要将大量的精力用于应付测试夹具准 备、测试现场恢复、访问测试数据操做结果等边缘性的工做中。Mockito、Unitils、Dbunit等框架的出现,这些问题有了很好的解决方案,特 别是Unitils结合Dbunit对测试DAO层提供了强大的支持,大大提升了编写测试用例的效率和质量。
也许在单元测试框架领域,testNG、JUnit的高下上尚有争论,它们各有本身的拥趸,可是在测试模拟领域,Mockito无疑是翘楚,JMock等只能站后了。
模拟测试概述
目前支持Java语言的Mock测试工具备EasyMock、JMock、Mockito、MockCreator、Mockrunner、 MockMaker等,Mockito是一个针对Java的Mocking框架。它与EasyMock和JMock很类似,是一套经过简单的方法对于指定 的接口或类生成 Mock 对象的类库,避免了手工编写Mock对象。但Mockito是经过在执行后校验什么已经被调用,它消除了对指望行为(Expectations)的须要。 使用Mockito,在准备阶段只需花费不多的时间,可使用简洁的API编写出漂亮的测试,能够对具体的类建立Mock对象,而且有“监视”非Mock 对象的能力。
Mockito使用起来简单,学习成本很低,并且具备很是简洁的API,测试代码的可读性很高,所以它十分受欢迎,用户群愈来愈多,不少开源软件也选择了 Mockito。要想了解更多有关Mockito的信息,能够访问其官方网站http://www.mockito.org/。在开始使用Mockito 以前,先简单了解一下Stub和Mock的区别。相比Easymock,JMock,编写出来的代码更加容易阅读。无须录制mock方法调用就返回默认值 是一个很大优点。目前最新的版本是1.9.0。
Stub对象用来提供测试时所须要的测试数据,能够对各类交互设置相应的回应。例如咱们能够设置方法调用的返回值等。Mockito中 when(…).thenReturn(…) 这样的语法即是设置方法调用的返回值。另外也能够设置方法在什么时候调用会抛出异常等。
Mock对象用来验证测试中所依赖对象间的交互是否可以达到预期。Mockito中用 verify(…).methodXxx(…) 语法来验证 methodXxx方法是否按照预期进行了调用。有关 stub和mock的详细论述请见Martin Fowler的文章《Mocks Aren't Stub》,地址为http://martinfowler.com/articles/mocksArentStubs.html。在Mocking框 架中所谓的Mock对象其实是做为上述的Stub和Mock对象同时使用的。由于它既能够设置方法调用返回值,又能够验证方法的调用。
建立Mock对象
能够对类和接口进行Mock对象的建立,建立的时候能够为Mock对象命名,也能够忽略命名参数。为Mock对象命名的好处就是调试的时候会很方便。比 如,咱们Mock多个对象,在测试失败的信息中会把有问题的Mock对象打印出来,有了名字咱们能够很容易定位和辨认出是哪一个Mock对象出现的问题。另 外它也有限制,对于final类、匿名类和Java的基本类型是没法进行Mock的。除了用Mock方法来建立模拟对象,如 mock(Class<T> classToMock),也可使用@mock注解定义Mock,下面咱们经过实例来介绍一下如何建立一个Mock对象。
html
在①处和②处,经过Mockito提供的mock()方法建立UserService 用户服务接口、用户服务实现类UserServiceImpl的模拟对象。在③处,经过@Mock注解建立用户User类模拟对象,并须要在测试类初始化 方法中,经过MockitoAnnotations.initMocks()方法初始化当前测试类中全部打上@Mock注解的模拟对象。若是没有执行这一 步初始化动做,测试时会报模拟对象为空对象异常。
设定Mock对象的指望行为及返回值
从上文中咱们已经知道能够经过when(mock.someMethod()).thenReturn(value)来设定Mock对象的某个方法调用时 的返回值,但它也一样有限制条件:对于static和final修饰的方法是没法进行设定的。下面咱们经过实例来介绍一下如何调用方法及设定返回值。 框架
在①处,模拟测试接口UserService的findUserByUserName()方法、hasMatchUser()方法及 registerUser()方法。在①-1处经过when().thenReturn()语法,模拟方法调用及设置方法的返回值,实例经过模拟调用 UserService 用户服务接口的查找用户findUserByUserName()方法,查询用户名为“tom”详细的信息,并设置返回User对象:new User("tom", "1234")。在①-2处经过doReturn (). when ()语法,模拟判断用户hasMatchUser()方法的调用,判断用户名为“tom”及密码为“1234”的用户存在,并设置返回值为:true。在 ①-3处对void方法进行方法预期设定,如实例中调用注册用户registerUser()方法。设定调用方法及返回值以后,就能够执行接口方法调用验 证。在②处和③处,模拟测试用户服务实现类UserServiceImpl,测试的方法与模拟接口一致。
验证交互行为
Mock对象一旦创建便会自动记录本身的交互行为,因此咱们能够有选择地对其交互行为进行验证。在Mockito中验证mock对象交互行为的方法是 verify(mock). xxx()。因而用此方法验证了findUserByUserName()方法的调用,由于只调用了一次,因此在verify中咱们指定了times参数 或atLeastOnce()参数。最后验证返回值是否和预期同样。 dom
Mockio为咱们提供了丰富调用方法次数的验证机制,如被调用了特定次数verify(xxx, times(x))、至少x次verify(xxx, atLeast (x))、最多x次verify(xxx, atMost (x))、从未被调用verify(xxx, never())。在①-6处,验证findUserByUserName()方法至少被调用一次。在①-7处,验证 findUserByUserName()方法至多被调用一次。ide
http://stamen.iteye.com/blog/1470066工具