• 【项目经验】Mockito教程


    一、教程

    转载:https://blog.csdn.net/sdyy321/article/details/38757135/

    官网: http://mockito.org

    源码分析:https://www.cnblogs.com/dengshihuang/p/7903550.html

    属性默认值:https://yanbin.blog/mockito-mocked-default-fields-method-returns/#more-8359

    API文档:http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html

    项目源码:https://github.com/mockito/mockito
    使用案例:https://blog.csdn.net/Christopher36/article/details/81036683

    首先添加maven依赖

     <dependency>
              <groupId>org.mockito</groupId>
              <artifactId>mockito-all</artifactId>
              <version>1.9.5</version>
              <scope>test</scope>
          </dependency>
    View Code

    当然mockito需要junit配合使用

    <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
          </dependency>
    View Code

    然后为了使代码更简洁,最好在测试类中导入静态资源

    import static org.mockito.Mockito.*;
    import static org.junit.Assert.*;
    View Code

    下面我们开始使用mockito来做测试

    package com.spring.sxf.mockito;
    
    
    
    import org.junit.Test;
    import org.mockito.ArgumentMatcher;
    import org.mockito.InOrder;
    import org.mockito.Mock;
    import org.mockito.MockitoAnnotations;
    import org.mockito.exceptions.verification.NoInteractionsWanted;
    
    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.List;
    
    
    import static org.mockito.Mockito.*;
    import static org.junit.Assert.*;
    
    /**
     * @author <a href="mailto:shangxiaofei@meituan.com">尚晓飞</a>
     * @date 7:52 PM 2019/4/26
     */
    public class MockitoTest {
    
        //验证要mock的对象,是否发生过某些行为
        @Test
        public void testArrayList() {
            //生成mock对象
            ArrayList<String> mockList = mock(ArrayList.class);
            //使用mock的对象
            mockList.add("SXF");
            mockList.add("456");
    
    
            //验证行为add("SXF"),add("123")是否发生过
            verify(mockList).add("SXF");
            verify(mockList).add("456");
        }
    
        //模拟我们所期望的结果
        @Test
        public void testArrayList1() {
            //生成mock对象
            ArrayList<String> mockList = mock(ArrayList.class);
            //
            when(mockList.size()).thenReturn(2);
            int size = mockList.size();
            assertEquals(2, size);
    
    
        }
    
        //模拟我们期望的结果
        @Test(expected = NullPointerException.class)
        public void when_thenThrow() throws IOException {
            OutputStream outputStream = mock(OutputStream.class);
            OutputStreamWriter writer = new OutputStreamWriter(outputStream);
            //预设当流关闭时抛出异常
            doThrow(new IOException()).when(outputStream).close();
            outputStream.close();
        }
    
        //参数匹配
        @Test
        public void with_arguments() {
            Comparable comparable = mock(Comparable.class);
            //预设根据不同的参数返回不同的结果
            when(comparable.compareTo("Test")).thenReturn(1);
            when(comparable.compareTo("Omg")).thenReturn(2);
            assertEquals(1, comparable.compareTo("Test"));
            assertEquals(2, comparable.compareTo("Omg"));
            //对于没有预设的情况会返回默认值
            assertEquals(0, comparable.compareTo("Not stub"));
        }
    
    
        //除了匹配制定参数外,还可以匹配自己想要的任意参数
        @Test
        public void with_unspecified_arguments() {
            List list = mock(List.class);
            //匹配任意参数
            when(list.get(anyInt())).thenReturn(1);
            when(list.contains(argThat(new IsValid()))).thenReturn(true);
            assertEquals(1, list.get(1));
            assertEquals(1, list.get(999));
            assertTrue(list.contains(1));
            assertTrue(!list.contains(3));
        }
    
        private class IsValid extends ArgumentMatcher<List> {
            @Override
            public boolean matches(Object o) {
                return (Integer) o == 1 || (Integer) o == 2;
            }
        }
    
    
        //需要注意的是如果你使用了参数匹配,那么所有的参数都必须通过matchers来匹配
        @Test
        public void all_arguments_provided_by_matchers() {
            Comparator comparator = mock(Comparator.class);
            comparator.compare("nihao", "hello");
            //如果你使用了参数匹配,那么所有的参数都必须通过matchers来匹配
            verify(comparator).compare(anyString(), eq("hello"));
            //下面的为无效的参数匹配使用
            //verify(comparator).compare(anyString(),"hello");
        }
    
        //验证确切的调用次数
        @Test
        public void verifying_number_of_invocations() {
            List list = mock(List.class);
            list.add(1);
            list.add(2);
            list.add(2);
            list.add(3);
            list.add(3);
            list.add(3);
            //验证是否被调用一次,等效于下面的times(1)
            verify(list).add(1);
            verify(list, times(1)).add(1);
            //验证是否被调用2次
            verify(list, times(2)).add(2);
            //验证是否被调用3次
            verify(list, times(3)).add(3);
            //验证是否从未被调用过
            verify(list, never()).add(4);
            //验证至少调用一次
            verify(list, atLeastOnce()).add(1);
            //验证至少调用2次
            verify(list, atLeast(2)).add(2);
            //验证至多调用3次
            verify(list, atMost(3)).add(3);
    
        }
    
        //模拟方法体抛出异常
        @Test(expected = RuntimeException.class)
        public void doThrow_when() {
            List list = mock(List.class);
            doThrow(new Exception()).when(list).add(1);
            list.add(1);
        }
    
        //验证执行顺序
        @Test
        public void verification_in_order() {
            List list = mock(List.class);
            List list2 = mock(List.class);
            list.add(1);
            list2.add("hello");
            list.add(2);
            list2.add("world");
            //将需要排序的mock对象放入InOrder
            InOrder inOrder = inOrder(list, list2);
            //下面的代码不能颠倒顺序,验证执行顺序
            inOrder.verify(list).add(1);
            inOrder.verify(list2).add("hello");
            inOrder.verify(list).add(2);
            inOrder.verify(list2).add("world");
        }
    
    
        //确保模拟对象上无互动发生
        @Test
        public void verify_interaction(){
            List list = mock(List.class);
            List list2 = mock(List.class);
            List list3 = mock(List.class);
            list.add(1);
            verify(list).add(1);
            verify(list,never()).add(2);
            //验证零互动行为
            verifyZeroInteractions(list2,list3);
        }
    
        //找出冗余的互动(即未被验证到的)
        @Test(expected = NoInteractionsWanted.class)
        public void find_redundant_interaction(){
            List list = mock(List.class);
            list.add(1);
            list.add(2);
            verify(list,times(2)).add(anyInt());
            //检查是否有未被验证的互动行为,因为add(1)和add(2)都会被上面的anyInt()验证到,所以下面的代码会通过
            verifyNoMoreInteractions(list);
    
            List list2 = mock(List.class);
            list2.add(1);
            list2.add(2);
            verify(list2).add(1);
            //检查是否有未被验证的互动行为,因为add(2)没有被验证,所以下面的代码会失败抛出异常
            verifyNoMoreInteractions(list2);
        }
    
        //9、使用注解来快速模拟
        //在上面的测试中我们在每个测试方法里都mock了一个List对象,为了避免重复的mock,是测试类更具有可读性,我们可以使用下面的注解方式来快速模拟对象:
        @Mock
        private List mockList;
        //构造方法
        public MockitoTest(){
            MockitoAnnotations.initMocks(this);
        }
    
        @Test
        public void shorthand(){
            mockList.add(1);
            verify(mockList).add(1);
        }
    
    
    }
    View Code

    二、spring项目+单元测试使用mockito

    一、单元测试类

    @Slf4j
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:spring/applicationContext.xml"})
    public class RouteServiceTest {
    
        //要被mock的接口
        @Mock
        private IChannelQueueCountService iChannelQueueCountService;
    
        //使用了要被mock对象的类,需要注入mock对象
        @InjectMocks
        @Autowired
        private ChannelChooseService channelChooseService;
    
        //发起调用的接口
        @Autowired
        private TRouteService.Iface tRouteService;
    
        //mock对象注入
        @Before
        public void setUp() {
            MockitoAnnotations.initMocks(this);
        }
    
        @Test
        public void test01() throws TException {
    
            when(iChannelQueueCountService.getChannelQueueCounts(anyList(), anyLong(), anyBoolean())).thenAnswer(new Answer<Map<Integer, Integer>>() {
    
                @Override
                public Map<Integer, Integer> answer(InvocationOnMock invocation) throws Throwable {
                    HashMap<Integer, Integer> map = new HashMap<>();
                    Object[] args = invocation.getArguments();
                    List<Integer> ids = (List<Integer>) args[0];
                    for (Integer id : ids) {
                        map.put(id, 1);
                    }
                    return map;
                }
            });
    
    
            TChooseChannelReq tChooseChannelReq = new TChooseChannelReq(56789, 219, 999, 6000, "shangxiaofei", "6212260200052453285", TPPType.PRIVATE, 10, 34, 99999);
            TChooseChannelRes res = tRouteService.chooseChannel(tChooseChannelReq);
            System.out.println("接口调用返回:" + res.getLogicalChannelId());
    
        }
    }
    View Code
  • 相关阅读:
    sql count中加条件
    zero-copy总结
    问题诊断神器arthas
    rabbitmq 消息确认
    HttpRunner安装笔记(1)安装环境准备:pyenv安装
    centos7 安装rabbitmq3.4.1-1
    centos7 python2.7.5 升级python3.6.4
    测试面试必会sql(1)
    mysql5.6 无法远程连接问题解决
    Katalon 学习笔记(一)
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/10775191.html
Copyright © 2020-2023  润新知