Mockito 单元测试简介以及Stub

Mockito简介

Mock是单元测试工具的简称,Mock可以理解为模拟对象。
在传统的JUnit单元测试中,我们没有消除在测试中对对象的依赖。如存在A对象方法依赖B对象方法,在测试A对象的时候,我们需要构造出B对象,这样子增加了测试的难度,或者使得我们对某些类的测试无法实现。这与单元测试的思路相违背。
Mockito是一个Java开源的测试框架,Mockito在测试中尝试移除我们传统JUnit单元测试中使用的Expect方式,这样子有效降低代码的耦合。使得我们只测试我们需要的方法和类,而不需过多的考虑依赖类。

Mockito的简单使用

在使用Mockito之前,我们需要下载和在我们工程中引入Jar包。
我们根据官方的入门文档,首先开始对一个List的基本测试。代码如下:

package com .jing .mockito .listTest ;
import java .util . List ;
import org .junit .Before ;
import org .junit .Test ;
import static org .mockito .Mockito .*;
/**
 * 简单使用Mockito对List的部分方法模拟测试
 * @author jinglongjun
 *
 */

public  class ListTest  {
    
     private List <String >  list ;
    
     @SuppressWarnings ( "unchecked" )
     @Before
     public void setUp ( ) {
        
         list  = mock ( List . class ) ;
     }
     @Test
      public void testAdd ( ) {
         
          list .add ( "one" ) ;
          list .clear ( ) ;
         
         verify ( list ) .add ( "one" ) ;
         verify ( list ) .clear ( ) ;
      }
}

具体代码也可以查看官方文档:http://mockito.org/

Mockito的 Stub基本使用

下面我们模拟一个Dao,以及Service的组合调用。代码参考:http://www.oschina.net/translate/mockito-a-great-mock-framework-for-java-development

public  class Person  {
     private Long id ;
     private int age ;
     private String name ;
package com .jing .mockito .dao ;
public  interface IPersonDao  {
    int deletePerson (Long id ) ;
}
package com .jing .mockito .service ;
import java .util . List ;
public  interface IPersonService  {
     /**
     * 根据ID删除用户
     * 
     * @param id
     * @return
     */

     public int deletePersonById (Long id ) ;

public  class PersonService implements IPersonService  {
       IPersonDao personDao ;

     @Override

     public int deletePersonById (Long id )  {
        int result  =  0 ;

        try {
            result  = personDao .deletePerson (id ) ;

         }catch (Exception e ) {
            e .printStackTrace ( ) ;
         }

         return result ;
     }

我们首先模拟对delte方法的简单测试。

package com .jing .mockito .service ;
import org .junit .Before ;
import org .junit .Test ;
import org .mockito .Mockito ;
import com .jing .mockito .dao .IPersonDao ;
public  class PersonServiceTest  {
     private PersonService personService ;
    
     @Before
     public void setup ( ) {
        
         //Mock出对应的对象
        personService  = Mockito .mock (PersonService . class ) ;
        personService .personDao  = Mockito .mock (IPersonDao . class ) ;
     }
     @Test
     public void deletePersonSuccess ( ) {
        
        Mockito .when (personService .deletePersonById (1000L ) ) .thenReturn ( 1 ) ;
     }
}

以上代码只是简单的对delete方法测试,相对而言,代码的耦合度还是比较低。
从以上低耦合的代码中,我们可以看到Mockito在单元测试中的一个基本使用,即Stub(存根)。Stub就是把需要测试的数据塞进对象中,使用基本为

Mockito .when ( ... ) .thenReturn ( ... ) ;

使用Stub使我们只关注于方法调用和放回结果。一个方法被Stub后,该方法就只返回该结果。对此我们需要注意:
-1,static ,final方法,无法进行Stub操作。
-2,当连续为一个方法Stub时,只会调用最近的一次。
如下测试代码:

@Test
     public void testStub ( ) {
        
        when ( list .get ( 0 ) ) .thenReturn ( "a" ) ;
         Assert .assertEquals ( "a" ,  list .get ( 0 ) ) ;
        
        when ( list .get ( 0 ) ) .thenReturn ( "a" ) ;
        when ( list .get ( 0 ) ) .thenReturn ( "b" ) ;
         Assert .assertEquals ( "b" ,  list .get ( 0 ) ) ;
     }

对于返回值为void的方法,我们也可以Stub,不过不是调用thenReturn而已。

@Test
     public void testStubVoid ( ) {
        
         //1.使用doNothing来调用返回值为空的add方法。
        doNothing ( ) .when ( list ) .add ( 0 ,  "a" ) ;
         //2,直接调用notify
        when ( list ) .notify ( ) ;
     }

在Stub时候,我们可以对方法抛出异常。

@Test
     public void testThrowsException ( ) {
        
         //1,调用add方法时,抛出异常
        when ( list .add ( "a" ) ) .thenThrow ( new RuntimeException ( ) ) ;
         list .add ( "a" ) ;
         //2,空方法抛出异常
        doThrow ( new RuntimeException ( ) ) .when ( list ) .add ( 0 ,  "a" ) ;
         list .add ( 0 ,  "a" ) ;
         //3,连续调用。第一次调用方法时什么都不做,第二次调用时,抛出异常
        doNothing ( ) .doThrow ( new RuntimeException ( ) ) .when ( list ) .add ( 0 ,  "a" ) ;
         list .add ( 0 ,  "a" ) ;
         list .add ( 0 ,  "a" ) ;
     }

我们运行测试可以发现,在Stub对应方法后,方法如我们期望,在调用时抛出了异常。

参考内容:

http://blog.csdn.net/zhangxin09/article/details/42422643

http://qiuguo0205.iteye.com/blog/1443344

http://www.oschina.net/translate/mockito-a-great-mock-framework-for-java-development

你可能感兴趣的:(java,测试,mockito,单元测试,JUnit)