Mockito 测试介绍

测试工作中,比较耗费时间的工作:


对远程数据库的依赖

调用第三方应用的耗时(主要是网络交互错误、响应时间)

运行较慢的系统(需要等待)

真实对象尚不存在(比如需要用到其他产品的部分模块)

对于第三方模拟模块的生成一直是个考验开发人员耐力、积极性的,为了提高测试驱动开发的效率,我们选择了眼下比较常用的测试框架:


Mockito

英文文档地址:http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html

mock 限制:对于final类、匿名类和Java的基本类型是无法进行mock。


项目最新版本pom依赖:

<!-- pom依赖 -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>1.9.5</version>
    <scope>test</scope>
</dependency>


mockito 中annonation

@Mock:被该注解标识的对象为mock对象。如: @Mock private ArticleCalculator calculator;

@InjectMocks:此注解是将已有的mock对象,通过类型、名字来注入到被测试类中的使用的。

@Spy:表示该实际对象的行为是被mockito所监视。

@Captor: 参数捕获器捕获方法参数进行验证

要使annonation起到作用:

1、在测试类中初始化annonation的配置:MockitoAnnotations.initMocks(testClass);  即测试类中有@Before注解标注的方法中。

2、可以使用测试类中使用运行器:@RunWith(MockitoJUnitRunner.class) 。

 

mockito 使用Demo:

远程数据库的demo:

// 业务测试类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.pm.dao.BaseDao;
@Component("baseBiz")
public class BaseBiz {
     
    @Autowired
    private BaseDao baseDao;
     
    public Map<String, Object> getUser(String userName){
        return baseDao.getUser(userName);
    }
         
    public Map<String, Object> getUserThrow(String userName) throws Exception {
        return baseDao.getUser(userName);
    }
    public String getUserCard(String userName){
        return baseDao.getUserCard(userName);
    }
}
 
// 操作数据库类
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Component;
@Component("baseDao")
public class BaseDao {
     
    public Map<String, Object> getUser(String userName){
        Map<String, Object>  map = new HashMap<String, Object>();
        map.put("userName", userName);
        return map;
    }
     
    public Map<String, Object> getUserThrow(String userName) throws Exception {
        Map<String, Object>  map = new HashMap<String, Object>();
        map.put("userName", userName);
        return map;
    }
 
    public String getUserCard(String userName) {
        return userName == null || userName.length() ==0 ? "userName is null" : userName + "4502399489548283848";
    }
}


测试用例:

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import java.util.HashMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.util.ReflectionTestUtils;
import com.pm.dao.BaseDao;
//ReflectionTestUtils.setField(baseBiz, "baseDao", baseDao); 设置mock对象
@RunWith(MockitoJUnitRunner.class)
public class BaseBizTest {
    private Logger logger = LoggerFactory.getLogger(getClass());
     
    @InjectMocks
    private BaseBiz baseBiz;
    @Mock
    private BaseDao baseDao;
     
    @Spy
    private BaseDao baseDaoSpy;
    @Captor
    private ArgumentCaptor<String> captor;
    @Before
    public void setUp() {
//      baseDao = mock(BaseDao.class);
//      MockitoAnnotations.initMocks(this);
    }
     
    // 用于返回值设定
    @Test
    public void testGetUser() {
        Map<String, Object> returnMap = new HashMap<String, Object>();
        returnMap.put("userName", "returnMap");
        when(baseDao.getUser("xiaoxiao")).thenReturn(returnMap);
         
        Map<String, Object> user = baseBiz.getUser("xiaoxiao");
        logger.info(user.toString());
         
        verify(baseDao).getUser("xiaoxiao");
    }
     
    @Test
    public void testGetUserAnswer() {
        Map<String, Object> returnMap = new HashMap<String, Object>();
        returnMap.put("userName", "returnMap");
         
        String userName = "abc";
        when(baseDao.getUser(userName)).thenAnswer(new Answer<Map<String, Object>>() {
            /**
             * invocation 中方法
             * getArguments()  调用后会以Object数组的方式返回mock方法调用的参数。 
             * getMethod()  返回java.lang.reflect.Method 对象 
             * getMock()  返回mock对象 
             * callRealMethod()  真实方法调用,如果mock的是接口它将会抛出异常 
             */
            public Map<String, Object> answer(InvocationOnMock invocation) throws Throwable {
                Map<String, Object> returnMap = new HashMap<String, Object>();
                returnMap.put("userName", "xiaoxiao");
                Object[] argus = invocation.getArguments();
                if (!argus[0].equals("xiaoxiao")){
                    returnMap = new HashMap<String, Object>();
                    returnMap.put("userName", "returnMap");
                }
                return returnMap;
            }
             
        });
         
        Map<String, Object> user = baseBiz.getUser(userName);
        logger.info(user.toString());
         
        verify(baseDao).getUser(userName);
    }
    // 设置方法调用时产生异常
    @Test(expected=Exception.class)
    public void testGetUserThrowThenThrow() throws Exception {
        Map<String, Object> returnMap = new HashMap<String, Object>();
        returnMap.put("userName", "returnMap");
         
        when(baseDao.getUser("xiaoxiao")).thenThrow(new Exception());
     
        Map<String, Object> user = baseBiz.getUser("xiaoxiao");
        logger.info(user.toString());
         
        verify(baseDao).getUser("xiaoxiao");
    }
     
    @Test
    public void testGetUserThrowDoThrow() throws Exception {
        Map<String, Object> returnMap = new HashMap<String, Object>();
        returnMap.put("userName", "returnMap");
         
        doThrow(new Exception()).when(baseDao).getUserThrow("xiaoxiao");
        Map<String, Object> user = baseBiz.getUser("xiaoxiao");
        logger.info(user.toString());
         
        verify(baseDao).getUser("xiaoxiao");
    }
    // 主要用于验证
    @Test
    public void testArgumentCaptor() {
        baseBiz.getUser("xiaoxiao");
        baseBiz.getUser("mengmeng");
//       验证参数是否传递正确 ,是否被调用两次
//      captor.capture() 捕获方法参数 
//      captor.getValue() 获取方法参数值,如果方法进行了多次调用,它将返回最后一个参数值 
//      captor.getAllValues() 方法进行多次调用后,返回多个参数值 
        verify(baseDao, times(2)).getUser(captor.capture());
         
        logger.info(captor.getValue());
//      assertEquals("xiaoxiao", captor.getValue());
        assertEquals("mengmeng", captor.getValue());
    }
     
    // 用于参数匹配,无需关心参数值
    @Test
    public void testArgumentMatcher() {
        Map<String, Object> returnMap = new HashMap<String, Object>();
        returnMap.put("userName", "returnMap");
         
        when(baseDao.getUser(anyString())).thenReturn(returnMap);
        logger.info(baseBiz.getUser("hello").toString());
         
        verify(baseDao).getUser("hello");
        verify(baseDao).getUser(eq("hello"));
    }
    // 用于参数判断是否符合方法需要
    // 自定义参数匹配规则 如果不是XiaoXiao将匹配失败
    @Test
    public void testArgumentMatcherCustom() {
        Map<String, Object> returnMap = new HashMap<String, Object>();
        returnMap.put("userName", "returnMap");
     
        class XiaoXiaoFalse extends ArgumentMatcher<String> {
            @Override
            public boolean matches(Object argument) {
                return ((String)argument).equals("XiaoXiao");
            } 
        } 
         
        // argThat(Matcher<T> matcher)方法用来应用自定义的规则
        when(baseDao.getUser(argThat(new XiaoXiaoFalse()))).thenReturn(returnMap);
         
        logger.info(baseBiz.getUser("XiaoXiao").toString());
         
        verify(baseDao).getUser(argThat(new XiaoXiaoFalse()));
    }
     
    // spy 真实Object,只stub其中部分的方法,其他方法继续真实的跑。 针对spy【监控】 真实Object 时少用、慎用when 的语法, 尽量用doReturn语法
    @Test
    public void testSpy() {        
        Map<String, Object> returnMap = new HashMap<String, Object>();
        returnMap.put("userName", "returnMap");
 
        doReturn(returnMap).when(baseDaoSpy).getUser("xiaojian");
//      when(baseDaoSpy.getUser("xiaojian")).thenReturn(returnMap);
        ReflectionTestUtils.setField(baseBiz, "baseDao", baseDaoSpy);
        Map<String, Object> user = baseBiz.getUser("xiaojian");
        logger.info(user.toString());
        logger.info(baseBiz.getUserCard("xiaojian"));
        verify(baseDaoSpy).getUser("xiaojian");
 
    }
     
}

 


转载于:https://my.oschina.net/mingpeng/blog/219949

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值