zoukankan      html  css  js  c++  java
  • Mockito+Junit5单元测试

    参考:
    https://segmentfault.com/a/1190000006746409
    https://waylau.com/mockito-quick-start/

    1.引入依赖

    下面这个最新版本匹配似乎有问题

        testCompile group: 'org.mockito', name: 'mockito-core', version: '3.7.7'
        testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: '3.7.7'
        testCompile group: 'org.junit.jupiter', name: 'junit-jupiter', version: '5.7.0'
    

    改用下面的旧版本测试成功

        testCompile group: 'org.mockito', name: 'mockito-core', version: '2.18.3'
        testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: '2.18.3'
        testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.2.0'
    

    2.编写测试用例

    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.mockito.ArgumentCaptor;
    import org.mockito.InOrder;
    import org.mockito.Mockito;
    
    import java.util.*;
    
    /**
     * @author zhengqian
     * @date 2021.01.22
     */
    public class CommonTest {
    
        @Test
        public void createMockObject() {
            // 使用 mock 静态方法创建 Mock 对象.
            List mockedList = Mockito.mock(List.class);
            Assertions.assertTrue(mockedList instanceof List);
    
            // mock 方法不仅可以 Mock 接口类, 还可以 Mock 具体的类型.
            ArrayList mockedArrayList = Mockito.mock(ArrayList.class);
            Assertions.assertTrue(mockedArrayList instanceof List);
            Assertions.assertTrue(mockedArrayList instanceof ArrayList);
        }
    
        @Test
        public void configMockObject() {
            List mockedList = Mockito.mock(List.class);
    
            // 我们定制了当调用 mockedList.add("one") 时, 返回 true
            Mockito.when(mockedList.add("one")).thenReturn(true);
            // 当调用 mockedList.size() 时, 返回 1
            Mockito.when(mockedList.size()).thenReturn(1);
    
            Assertions.assertTrue(mockedList.add("one"));
            // 因为我们没有定制 add("two"), 因此返回默认值, 即 false.
            Assertions.assertFalse(mockedList.add("two"));
            Assertions.assertEquals(mockedList.size(), 1);
    
            Iterator i = Mockito.mock(Iterator.class);
            Mockito.when(i.next()).thenReturn("Hello,").thenReturn("Mockito!");
            String result = i.next() + " " + i.next();
            //assert
            Assertions.assertEquals("Hello, Mockito!", result);
        }
    
        @Test
        public void testVerify() {
            List mockedList = Mockito.mock(List.class);
            mockedList.add("one");
            mockedList.add("two");
            mockedList.add("three times");
            mockedList.add("three times");
            mockedList.add("three times");
            Mockito.when(mockedList.size()).thenReturn(5);
            Assertions.assertEquals(mockedList.size(), 5);
    
            // mockedList.add("one") 至少被调用了 1 次(atLeastOnce)
            Mockito.verify(mockedList, Mockito.atLeastOnce()).add("one");
            // mockedList.add("two") 被调用了 1 次(times(1))
            Mockito.verify(mockedList, Mockito.times(1)).add("two");
            // mockedList.add("three times") 被调用了 3 次(times(3))
            Mockito.verify(mockedList, Mockito.times(3)).add("three times");
            // mockedList.isEmpty() 从未被调用(never)
            Mockito.verify(mockedList, Mockito.never()).isEmpty();
        }
    
        @Test
        public void testSpy() {
            List list = new LinkedList();
            // 使用 spy() 部分模拟对象
            List spy = Mockito.spy(list);
    
            // 对 spy.size() 进行定制.
            Mockito.when(spy.size()).thenReturn(100);
    
            spy.add("one");
            spy.add("two");
    
            // 因为我们没有对 get(0), get(1) 方法进行定制,
            // 因此这些调用其实是调用的真实对象的方法.
            Assertions.assertEquals(spy.get(0), "one");
            Assertions.assertEquals(spy.get(1), "two");
    
            Assertions.assertEquals(spy.size(), 100);
        }
    
        @Test
        public void testCaptureArgument() {
            List<String> list = Arrays.asList("1", "2");
            List mockedList = Mockito.mock(List.class);
            ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class);
            mockedList.addAll(list);
            // 获取 mockedList.addAll 方法所传递的实参 list.
            Mockito.verify(mockedList).addAll(argument.capture());
    
            Assertions.assertEquals(2, argument.getValue().size());
            Assertions.assertEquals(list, argument.getValue());
        }
    
        @Test
        public void testArgumentMatcher() {
            List mockedList = Mockito.mock(List.class);
            //stubbing using built-in anyInt() argument matcher
            Mockito.when(mockedList.get(Mockito.anyInt())).thenReturn("element");
    
            //stubbing using custom matcher (let's say isValid() returns your own matcher implementation):
    //        when(mockedList.contains(argThat(isValid()))).thenReturn("element");
    
            //following prints "element"
            System.out.println(mockedList.get(999));
        }
    
        @Test
        public void testThrowAndVoid() {
            List mockedList = Mockito.mock(List.class);
            Mockito.when(mockedList.get(1)).thenThrow(new RuntimeException());
            //following throws runtime exception
            System.out.println(mockedList.get(1));
    
            Mockito.doThrow(new RuntimeException()).when(mockedList).clear();
            //following throws RuntimeException:
            mockedList.clear();
        }
    
        @Test
        public void testInOrder() {
            // A. Single mock whose methods must be invoked in a particular order
            List singleMock = Mockito.mock(List.class);
    
            //using a single mock
            singleMock.add("was added first");
            singleMock.add("was added second");
    
            //create an inOrder verifier for a single mock
            InOrder inOrder = Mockito.inOrder(singleMock);
    
            //following will make sure that add is first called with "was added first, then with "was added second"
            inOrder.verify(singleMock).add("was added first");
            inOrder.verify(singleMock).add("was added second");
    
            // B. Multiple mocks that must be used in a particular order
            List firstMock = Mockito.mock(List.class);
            List secondMock = Mockito.mock(List.class);
    
            //using mocks
            firstMock.add("was called first");
            secondMock.add("was called second");
    
            //create inOrder object passing any mocks that need to be verified in order
            InOrder inOrder2 = Mockito.inOrder(firstMock, secondMock);
    
            //following will make sure that firstMock was called before secondMock
            inOrder2.verify(firstMock).add("was called first");
            inOrder2.verify(secondMock).add("was called second");
    
        }
    
        @Test
        public void testConsecutiveStubbing() {
            List mockedList = Mockito.mock(List.class);
            Mockito.when(mockedList.get(0))
                    .thenThrow(new RuntimeException())
                    .thenReturn("foo");
            // 精简写法
            // when(mockedList.get(0)).thenReturn("one", "two", "three");
    
            //First call: throws runtime exception:
            mockedList.get(0);
    
            //Second call: prints "foo"
            System.out.println(mockedList.get(0));
    
            //Any consecutive call: prints "foo" as well (last stubbing wins).
            System.out.println(mockedList.get(0));
        }
    
        @Test
        public void testCallbackStubbing() {
            List mockedList = Mockito.mock(List.class);
            Mockito.when(mockedList.get(Mockito.anyInt())).thenAnswer(invocation -> {
                Object[] args = invocation.getArguments();
                return "called with arguments: " + args;
            });
    
            //the following prints "called with arguments: foo"
            System.out.println(mockedList.get(111));
        }
    }
    
    

    使用mock注解

    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.extension.ExtendWith;
    import org.mockito.Mock;
    import org.mockito.Mockito;
    import org.mockito.junit.jupiter.MockitoExtension;
    
    /**
     * @author zhengqian
     * @date 2021.01.27
     */
    @ExtendWith(MockitoExtension.class)
    public class UserServiceTest {
    
        @Mock
        private UserService userService;
    
        @Test
        public void testGet() {
            Mockito.when(userService.get()).thenReturn("fake user");
            Assertions.assertEquals(userService.get(), "fake user");
        }
    }
    

    3. 其他JUnit5注解

    @Test :表示方法是测试方法。但是与JUnit4的@Test不同,他的职责非常单一不能声明任何属性,拓展的测试将会由Jupiter提供额外测试

    @ParameterizedTest :表示方法是参数化测试,下方会有详细介绍

    @RepeatedTest :表示方法可重复执行,下方会有详细介绍

    @DisplayName :为测试类或者测试方法设置展示名称

    @BeforeEach :表示在每个单元测试之前执行

    @AfterEach :表示在每个单元测试之后执行

    @BeforeAll :表示在所有单元测试之前执行

    @AfterAll :表示在所有单元测试之后执行

    @Tag :表示单元测试类别,类似于JUnit4中的@Categories

    @Disabled :表示测试类或测试方法不执行,类似于JUnit4中的@Ignore

    @Timeout :表示测试方法运行如果超过了指定时间将会返回错误

    @ExtendWith :为测试类或测试方法提供扩展类引用

    补充

    如果运行test遇到以下错误:

    FAILURE: Build failed with an exception.
    * What went wrong:
    Execution failed for task ':test'.
    > No tests found for given includes: [org.example.mockito.demo.service.UserServiceTest.configMockObject](filter.includeTestsMatching)
    

    改一下IDEA配置
    图片名称

  • 相关阅读:
    leetcode33. Search in Rotated Sorted Array
    pycharm 设置sublime text3 monokai主题
    django class Meta
    leetcode30, Substring With Concatenation Of All Words
    Sublime text3修改tab键为缩进为四个空格,
    sublime text3 python打开图像的问题
    安装上imesupport输入法依然不跟随的解决办法,
    sublime text3 的插件冲突弃用问题,
    sublime text3 BracketHighlighter括号匹配的设置
    windows 下wget的使用
  • 原文地址:https://www.cnblogs.com/ylty/p/14313648.html
Copyright © 2011-2022 走看看