单元测试——Mockito框架

文章介绍了Mockito作为单元测试工具,如何帮助开发者在服务或应用的不同模块互相依赖时,通过模拟(Mock)方法来实现对自身代码的测试。文中详细讲解了Mockito的原理,包括mock对象的创建、打桩和验证,并提供了多个实践示例,如mockBean、mockStub、参数匹配、调用次数验证、顺序执行和捕获参数等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单元测试——Mockito框架

#一、单元测试介绍

在这里插入图片描述

二、Mock框架

  日常工作中很多时候我们都需要同事间的相互配合协作完成某些功能,所以我们经常会遇到服务或者应用内不同模块之间要互相依赖的场景。
   比如下面的场景,serviceA 中的 methodA() 方式依赖 serviceB 中的 methodB() 方法返回操作的结果。那如果我们要对自己的methodA() 方法进行编写单元测试,还需要等其他同事的methodB() 方法开发完成才行。
    那有没有什么办法我们可以跳过或者说模拟方法 B 的输出呢?这就引出了我们今天的主角 Mockito,一个优秀的 Mock 测试框架。

在这里插入图片描述

三、Mockito原理分析

1、mock对象

1)@MockBean 注解

使用MockitoPostProcessor类 ,实现BeanFactoryPostProcessor,自行创建mock对象,替换spring创建对象

2)mock对象创建(也可使用@Mock注解)

在这里插入图片描述

2、打桩 & 验证

在这里插入图片描述

四、实践 & 演示

Maven

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
</dependency>

# 或

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-all</artifactId>
    <version>2.0.2-beta</version>
</dependency>
package com.mockito;

import com.mockito.service.Card;
import com.mockito.service.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.MockBeans;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.io.IOException;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

/**
 * {@Code demoTest}
 *
 * @Author zhutaotao
 * @Date 2023/2/24 11:07
 */
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class DemoTest {

    /**
     * mock一个对象
     * @throws IOException
     */
    @Test
    public void mockBeanTest() throws IOException {
        Task taskService = mock(Task.class);
        taskService.doSomething();
        verify(taskService).doSomething();
        System.out.println("返回值:"+taskService.doSomething());
    }

    /**
     * 测试桩
     */
    @Test
    public void mockStubTest(){
        Task taskService = mock(Task.class);
        System.out.println("第0次:"+doReturn("1").when(taskService).doSomething());
        System.out.println("第一次:"+taskService.doSomething());
        verify(taskService).doSomething();
        System.out.println("返回值:"+taskService.doSomething());
    }

    /**
     * 参数匹配器
     */
    @Test
    public void mockParameterTest(){
        Task taskService = mock(Task.class);
        when(taskService.doSomething(eq("error"))).thenReturn("str");
        taskService.doSomething("str");
        verify(taskService).doSomething(anyString());
        System.out.println("返回值:"+taskService.doSomething("error"));
    }

    /**
     * 调用次数验证
     */
    @Test
    public void mockAtLeastTest(){
        Task taskService = mock(Task.class);
        when(taskService.doSomething(eq("error"))).thenReturn("str");
        taskService.doSomething("str");

        // 其它:only()  never()
        verify(taskService,atLeast(3)).doSomething(anyString());
        System.out.println("返回值:"+taskService.doSomething("error"));
    }

    /**
     * 无返回打桩
     */
    @Test
    public void mockVoidTest(){
        Task taskService = mock(Task.class);
        doThrow(new RuntimeException()).when(taskService).voidReturn();
        taskService.voidReturn();
    }

    /**
     * 顺序执行
     */
    @Test
    public void mockOrderTest(){
        List<String> taskService = mock(List.class);
        taskService.add("first");
        taskService.add("second");

        // 顺序
        InOrder inOrder =  inOrder(taskService);
        inOrder.verify(taskService).add("second");
        inOrder.verify(taskService).add("first");
    }


    /**
     * 捕获参数
     */
    @Test
    public void mockCaptureArgsTest(){
        Card card = mock(Card.class);
        card.getMoney("123456");

        //参数捕获
        ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
        verify(card).getMoney(argumentCaptor.capture());
        assertEquals("123456",argumentCaptor.getValue());

    }
}



package com.mockito;

import com.mockito.service.Car;
import com.mockito.service.Task;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.io.IOException;

import static org.mockito.Mockito.*;

/**
 * {@Code demoInjectTest}
 *
 * @Author zhutaotao
 * @Date 2023/2/24 14:53
 */
@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class DemoInjectTest {
    @InjectMocks
    private Task taskService;
    @Mock
    private Car car;

    @Before
    public void before(){
        MockitoAnnotations.openMocks(this);
    }
    /**
     * mock一个对象
     * @throws IOException
     */
    @Test
    public void mockBeanTest() throws IOException {
        taskService.doSomething();
        verify(taskService).doSomething();
        System.out.println("返回值:"+taskService.doSomething());
    }

    /**
     * mock内部成员变量
     * @throws IOException
     */
    @Test
    public void mockInjectTest() throws IOException {
        doReturn("new RuntimeException()").when(car).drive();
        System.out.println(taskService.doSomething());
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值