Mockito 测试实战总结

最近公司要求补充测试用例,正好借这个机会学习下mockito,记录下加深下记忆。

以下测试都是用的testng

1. 基本使用

java 复制代码
public class MyTest {
    @Test
    public void test() {
        final MockTest mockTest = Mockito.mock(MockTest.class);
        when(mockTest.get()).thenReturn("b");
        assertEquals(mockTest.get(), "b");
    }

    @Test
    public void test2() {
        assertNull(mockTest.get());
    }

    public static class MockTest {
        public String get() {
            return "a";
        }
    }
}

2. 注解

使用注解必须在使用前调用 MockitoAnnotations.openMocks(this);, 该方法最后也会调用 Mockito 中的方法。相关类 MockAnnotationProcessor SpyAnnotationEngine等。

mockito 自带注解

1. @Mock-mock 一个类,当调用该类中的方法时,都不会产生实际的调用

java 复制代码
public class MyTest {
    @Mock
    private MockTest mockTest;

    @BeforeClass
    public void before(){
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void test() {
        when(mockTest.get()).thenReturn("b");
        assertEquals(mockTest.get(), "b");
    }

    public static class MockTest {
        public String get() {
            return "a";
        }
    }
}

2. @Spy - 和 @Mock 类似,但是正好相反,该类的方法就会产生实际的调用

java 复制代码
public class MyTest1 {
    @Spy
    private MockTest mockTest;

    @BeforeClass
    public void before() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void test() {
        assertEquals(mockTest.get(), "a");
    }

    @Test
    public void test2() {
        when(mockTest.get()).thenReturn("b");
        assertEquals(mockTest.get(), "b");
    }

    public static class MockTest {
        public String get() {
            return "a";
        }
    }
}

注解版本和 @Mock 类似。

3. @InjectMocks - 产生一个真实的实例,并且会注入 @Mock 和 @Spy 的类。

typescript 复制代码
public class MyTest2 {
    @InjectMocks
    private MockTest mockTest;
    @Mock
    private InjectMockObj injectMockObj;
    @Spy
    private InjectSpybj injectSpybj;

    @BeforeClass
    public void before() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void test() {
        assertNull(mockTest.get());
    }

    @Test
    public void test2() {
        when(injectMockObj.get()).thenReturn("a");
        assertEquals(mockTest.get(), "a");
    }

    @Test
    public void test3() {
        assertEquals(mockTest.getSpy(), "a");
    }

    public static class MockTest {
        private InjectMockObj injectMockObj;
        private InjectSpybj injectSpybj;

        public String get() {
            return injectMockObj.get();
        }
        public String getSpy() {
            return injectSpybj.get();
        }
    }

    public static class InjectMockObj {
        public String get() {
            return "a";
        }
    }

    public static class InjectSpybj {
        public String get() {
            return "a";
        }
    }
}

4. @Captor

配合 verify 捕获参数。

typescript 复制代码
public class MyTest3 {
    @Mock
    private MockTest mockTest;
    @Captor
    private ArgumentCaptor<String> captor;

    private AutoCloseable closeable;

    @BeforeClass
    public void open() {
        closeable = MockitoAnnotations.openMocks(this);
    }

    @AfterClass
    public void release() throws Exception {
        closeable.close();
    }

    @Test
    public void shouldDoSomethingUseful() {
        mockTest.set("b");
        verify(mockTest).set(captor.capture());
        assertEquals("b", captor.getValue());
    }

    public static class MockTest {
        public String set(String a) {
            return "a";
        }
    }
}

Spring Boot 中的注解

@MockBean @SpyBean

和 @Mock @Spy 类似,只是多了一个步骤,会把生成的类替换掉 ApplicationContext 中的类。

常用方法

  1. when(..).thenReturn(..)
  2. doReturn(..).doReturn().when(..).doStuff()

注意在一个方法上可以打两个桩然后有不同的操作,当调用时也会有不同的操作

csharp 复制代码
public class MyTest4 {
    @Mock
    private MockTest mockTest;

    @BeforeClass
    public void before(){
        MockitoAnnotations.openMocks(this);
    }


    @Test
    public void test() {
        doReturn("b").doReturn("z").when(mockTest).get();
        assertEquals(mockTest.get(), "b");
        assertEquals(mockTest.get(), "z");
    }

    @Test
    public void test1() {
        assertNull(mockTest.get());
    }

    public static class MockTest {
        public String get() {
            return "a";
        }
    }
}

参数匹配

只有当调用的方法的参数和类型和数量匹配时才能触发打桩点。

  1. ArgumentMatchers.any() 匹配任何参数
  2. ArgumentMatchers.anyString() 匹配任务字符串
  3. ArgumentMatchers.anyInt() 匹配任何Integer值
  4. ArgumentMatchers.eq() 匹配某个值
  5. 等等

总结

在使用了几天的 Mockito 之后,我的感受:

  1. 可以自定义的控制外部依赖对于测试的影响,当外部请求比较复杂时,可以使用 Mockito 来 mock 数据,而无需真正的去调用外部请求。
  2. 无需自己创建mock数据,减少工作量。
相关推荐
Zero_pl21 小时前
黑盒测试、白盒测试、单元测试、集成测试、系统测试、验收测试的区别与联系
单元测试·集成测试
风与沙的较量丶1 天前
单元测试方法的使用
单元测试·log4j
odoo中国1 天前
Part 3 第十二章 单元测试 Unit Testing
单元测试·软件工程
Zero_pl1 天前
单元测试的策略有哪些,主要包括什么?
单元测试
陈小咩咩1 天前
IDEA单元测试插件 SquareTest 延长试用期权限
java·单元测试·intellij-idea
ihengshuai3 天前
Jest单元测试
单元测试·jest·前端自动化测试
leo_hush3 天前
使用spring-boot-starter-test做单元测试简单示例
java·spring boot·单元测试
seasugar3 天前
单元测试整理
单元测试
程序员 小濠4 天前
2024Selenium自动化常见问题及解决方式!
自动化测试·软件测试·测试工具·单元测试·测试用例·接口测试·性能测试
刘一二6 天前
Spring单元测试(一)入门与实践
spring·junit·单元测试