mockit

简介

一、什么是mock测试,什么是mock对象?

 

先来看看下面这个示例:

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

 

一种替代方案就是使用mocks

从图中可以清晰的看出

mock对象就是在调试期间用来作为真实对象的替代品。

mock测试就是在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试。

知道什么是mock测试后,那么我们就来认识一下mock框架---Mockito

Stub和Mock

相同点:Stub和Mock对象都是用来模拟外部依赖,使我们能控制。

不同点:而stub完全是模拟一个外部依赖,用来提供测试时所需要的测试数据。而mock对象用来判断测试是否能通过,也就是用来验证测试中依赖对象间的交互能否达到预期。在mocking框架中mock对象可以同时作为stub和mock对象使用,两者并没有严格区别。

mockito案例

pom

<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-all</artifactId>
			<version>1.8.5</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
			<scope>test</scope>
		</dependency>
package com.jmock.demo;

import org.junit.Test;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.junit.Assert;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import static org.mockito.Mockito.*;

/**
 * Created by zhongmin on 2016/9/8.
 */
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);
    }

    @Test
    public void argumentMatchersTest(){

        //创建mock对象
        List<String> mock = mock(List.class);

        //参数匹配,anyInt()匹配任何参数
        when(mock.get(anyInt())).thenReturn("hello").thenReturn("world");

        String result = mock.get(100)+" "+mock.get(201);

        //验证方法是否调用2次
        verify(mock,times(2)).get(anyInt());

        Assert.assertEquals("hello world",result);
    }

    @Test
    public void argumentMatchersAnyTest(){
        //创建mock对象
        Map mapMock = mock(Map.class);

        //参数匹配起匹配map参数
        when(mapMock.put(anyInt(),anyString())).thenReturn("world");

        mapMock.put(1,"hello");

        //校验方法是否被调用,注意参数匹配,由于使用了匹配器,verify也要使用匹配器,如下几种用法

//        verify(mapMock).put(anyInt(),eq("hello"));    //正确

//        verify(mapMock).put(eq(1),eq("hello"));       //正确

//        verify(mapMock).put(eq(1),"hello");       //错误

//        verify(mapMock).put(1,"hello");           //正确

//        verify(mapMock).put(anyInt(),anyString());    //正确

        verify(mapMock).put(1,eq("hello"));     //错误
    }

    /**
     * 参数行为测试
     */
    @Test
    public void verifyTestTest(){
        List<String> mock = mock(List.class);
        List<String> mock2 = mock(List.class);

        mock.get(0);
        mock.get(1);
        mock.get(2);

        mock2.get(0);

        verify(mock).get(2);
        verify(mock,never()).get(3);
        verifyNoMoreInteractions(mock);
    }

    /**
     * Answer接口(方法逾期回调接口)
     * PS:mock对象的方进行调用预期的设定可以通过thenReturn()来指定返回值,thenThrow()指定返回时所抛异常,
     * 通常来说这两个方法足以应对一般的需求。
     * 但有时我们需要自定义方法执行的返回结果,Answer接口就是满足这样的需求而存在的。
     */
    @Test
    public void answerTest(){
        List<String> mock = mock(List.class);

        //
        when(mock.get(4)).thenAnswer(new CustomAnswer());

        doAnswer(new CustomAnswer()).when(mock).clear();
    }

    private class CustomAnswer implements Answer<String>{
        @Override
        public String answer(InvocationOnMock invocation) throws Throwable {
            Object[] args = invocation.getArguments();
            Integer num = (Integer)args[0];
            System.out.println("num = "+num);
            if(num>3 ){
                return"yes";
            }else{
                throw new RuntimeException();
            }
        }
    }

    /**
     * 自定义参数匹配器
     */
    @Test
    public void argumentDefMatchersTest(){
        List mock = mock(List.class);

        //设置自定义参数匹配器
        when(mock.addAll(argThat(new IsListOfTwoElements()))).thenReturn(true);

        mock.addAll(Arrays.asList("one","two","three"));

        verify(mock).addAll(argThat(new IsListOfTwoElements()));
    }

    private class IsListOfTwoElements extends ArgumentMatcher<List>{
        @Override
        public boolean matches(Object argument) {
            return ((List)argument).size()==2;
        }
    }

    @Test
    public void argumentCaptorTest(){
        List mock = mock(List.class);
        List mock2 = mock(List.class);

        mock.add("John");

        mock2.add("Brian");
        mock2.add("Jim");

        //实例化参数捕获器
        ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(String.class);

        //捕获输入的参数
        verify(mock).add(argumentCaptor.capture());
        Assert.assertEquals("John",argumentCaptor.getValue());

        //当有多个参数调用,捕获最后输入的参数
       verify(mock2,times(2)).add(argumentCaptor.capture());
        Assert.assertEquals("Jim",argumentCaptor.getValue());

        //捕获所有参数
        Assert.assertArrayEquals(new Object[]{"Brian","Jim"},argumentCaptor.getAllValues().toArray());
    }

    @Test
    public void spyTest(){
        List list = new LinkedList();
        List spy = spy(list);

        when(spy.size()).thenReturn(100);

        spy.add("one");
        spy.add("two");

        System.out.println(spy.get(0));
        System.out.println(spy.size());

        verify(spy).add("one");
        verify(spy).add("two");

    }
}

  注解DEMO

package com.jmock.demo;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;

import java.util.LinkedList;
import java.util.List;

import static org.mockito.Mockito.*;

/**
 * Created by zhongmin on 2016/9/9.
 */
public class MockitoTest {
    @Mock
    private List<String> list;
    @Spy
    private List<String> spyList = new LinkedList<String>();

    @Before
    public void initMocks(){
        MockitoAnnotations.initMocks(this);
    }

    @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);
    }

    @Test
    public void spyTest(){
//        List list = new LinkedList();
//        List spy = spy(list);

        when(spyList.size()).thenReturn(100);

        spyList.add("one");
        spyList.add("two");

        System.out.println(spyList.get(0));
        System.out.println(spyList.size());

        verify(spyList).add("one");
        verify(spyList).add("two");

    }

}

 

推荐教程:http://wenku.baidu.com/view/8def451a227916888486d73f.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值