Mockito 单元测试简介以及Stub

来源:互联网 发布:乐视手机4g网络不能用 编辑:程序博客网 时间:2024/06/09 16:51

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

0 0
原创粉丝点击