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数据,减少工作量。
相关推荐
MC皮蛋侠客17 小时前
Google Test 单元测试指南
c++·单元测试·google test
英俊潇洒美少年2 天前
前端 Jest 单元测试零基础实战:模板、提效、避坑、面试题(Vue 项目可用)
前端·vue.js·单元测试
测试员周周6 天前
【Appium 系列】第18节-重试与容错 — 移动端测试的稳定性保障
人工智能·python·功能测试·ui·单元测试·appium·测试用例
测试员周周6 天前
【Appium 系列】第17节-XMind用例转换 — 从思维导图到 YAML
java·服务器·人工智能·单元测试·appium·测试用例·xmind
一路往蓝-Anbo6 天前
第五章:如何对 HAL 库本身进行单元测试?
网络·数据结构·stm32·单片机·嵌入式硬件·单元测试·tdd
计算机安禾6 天前
【c++面向对象编程】第49篇:面向对象的单元测试:用GoogleTest测试类
开发语言·c++·单元测试
测试员周周6 天前
【Appium 系列】第20节-测试项目结构设计 — 从脚本到工程
人工智能·数据挖掘·回归·单元测试·appium·测试用例·测试覆盖率
数字供应链安全产品选型6 天前
2025年Gartner中国安全技术成熟度曲线解读:软件供应链安全从“过热”到“落地”的演进之路
人工智能·web安全·单元测试·软件供应链安全
测试员周周7 天前
【Appium 系列】第14节-断言与验证 — Validator 的设计
android·人工智能·python·功能测试·ios·单元测试·appium