Spring Boot 单元测试笔记

spring,boot,单元测试,笔记 · 浏览次数 : 25

小编点评

**单元测试类 DemoServiceTest** ```java @DisplayName("单元测试用例") public class DemoServiceTest { @InjectMocks private DemoServiceImpl demoService; // 此处注意要使用Service接口的实现类 @Mock private DemoMapper demoMapper; // 对Mapper使用Mock @BeforeEach public void setUp() { // 准备数据 DemoOrder order1 = new DemoOrder(); order1.setOrderId("001"); order1.setOrderUser("User1"); // 其他属性略 DemoOrder order2 = new DemoOrder(); // ... 其他属性略 // 以下为mock mapper的方法模拟 // 1. 传String的方法,直接传入模拟的参数即可 when(demoMapper.selectOrderByOrderId("001")).thenReturn(order1); // 2. 传OrderParam的方法,需要将 when...thenReturn语法改为 doReturn...when... 语法 doReturn(Collections.singletonList(order1)) .when(demoMapper).selectOrderByOrderParam(argThat(new ArgumentMatcher<OrderParam>() { @Override public boolean match(OrderParam param) { return param.getOrderId().equals("001"); } })); // 此处也可以将 ArgumentMatcher 单独定义 doReturn(Collections.singletonList(order2)) .when(demoMapper).selectOrderByOrderParam(argThat(new ArgumentMatcher<OrderParam>() { @Override public boolean match(OrderParam param) { return param.getOrderId().equals("002"); } } )); } @Test public void findOrderByOrderIdTest() { String orderId = "001"; DemoOrder order = demoService.findOrderByOrderId(orderId); assertThat(order.getOrderUser()).isEqualTo("User1"); } @Test public void findOrderByOrderParamTest() { OrderParam param = new OrderParam(); param.setOrderId("002"); DemoOrder order = demoService.findOrderByOrderParam(param); assertThat(order.getOrderUser()).isEqualTo("User2"); } } ``` **其他说明** * 测试方法中使用 Mockito 框架来模拟 Mapper 接口。 * `@DisplayName` 注解用于为测试方法命名。 * `@Mock` 注解用于向 Mockito 框架创建一个 mock 对象。 * `@BeforeEach` 方法在每个测试方法之前运行。 * `when...thenReturn` 语句用于模拟方法的返回值。 * `ArgumentMatcher` 用于比较实际参数和模拟参数的属性值。

正文

1. 导入JUnit5测试框架

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.8.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <version>1.8.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.7.2</version>
    <scope>test</scope>
</dependency>

其他按 Spring Boot 项目标准,按需引入即可

2. 编写Service

/**
 * 假设一个订单类
 */
public class DemoOrder {
    private String orderId;
    private String orderUser;
    private String contents;
    private Integer quantity;
    private BigDecimal price;
    private BigDecimal total;

    // getter,setter略
}

Mapper 接口

@Mapper
public interface DemoOrderMapper {
    DemoOrder selectOrderByOrderId(String orderId);
    List<DemoOrder> selectOrderByOrderParam(OrderParam param);
}

Service

/**
 * DemoService
 * 此处的两个方法,一个是传入String,一个是传入封装好的参数类 OrderParam。这两种方法的测试方法不同
 */
public interface DemoService {
    DemoOrder findOrderByOrderId(String orderId);
    DemoOrder findOrderByRequestParam(OrderParam param);
}
@Service
public class DemoServiceImpl implements DemoService {
    @Autowired
    DemoMapper demoMapper;

    @Override
    public DemoOrder findOrderByOrderId(String orderId) {
        DemoOrder order = demoMapper.selectOrderByOrderId(orderId);
        return order;
    }

    @Override
    public DemoOrder findOrderByRequestParam(OrderParam param) {
        List<DemoOrder> orderList = demoMapper.selectOrderByRequestParam(param);
        return CollectionUtils.isEmpty(orderList) ? null : orderList.get(0);
    }
}

3. 编写测试类

@DisplayName("单元测试用例")
public class DemoServiceTest {
    @InjectMocks
    DemoServiceImpl demoService; // 此处注意要使用Service接口的实现类

    @Mock
    DemoMapper demoMapper; // 对Mapper使用Mock

    @BeforeEach
    public void setUp() {
        openMocks(this);
        // 老版本是 initMocks(this);
        // 准备数据
        DemoOrder order1 = new DemoOrder();
        order1.setOrderId("001");
        order1.setOrderUser("User1");
        order1.setContents("contents1");
        order1.setQuantity(1);
        order1.setPrice(new BigDecimal("10.5"));
        order1.setTotal(new BigDecimal("10.5"));

        DemoOrder order2 = new DemoOrder();
        order2.setOrderId("002");
        // ... 其他属性略

        DemoOrder order3 = new DemoOrder();
        order3.setOrderId("003");
        // ... 其他属性略

        // 以下为mock mapper的方法模拟
        // 1. 传String的方法,直接传入模拟的参数即可
        when(demoMapper.selectOrderByOrderId("001")).thenReturn(order1);
        when(demoMapper.selectOrderByOrderId("002")).thenReturn(order2);
        // ...

        // 2. 传OrderParam的方法,需要将 when...thenReturn语法改为 doReturn...when... 语法
        doReturn(Collections.singletonList(order1))
            .when(demoMapper).selectOrderByOrderParam(argThat(
                new ArgumentMatcher<OrderParam>() {
                    @Override
                    public boolean match(OrderParam param) {
                        return param.getOrderId().equals("001")
                    }
                }
        ));
        // 此处也可以将 ArgumentMatcher 单独定义

        doReturn(Collections.singletonList(order2))
            .when(demoMapper).selectOrderByOrderParam(argThat(
                new ArgumentMatcher<OrderParam>() {
                    @Override
                    public boolean match(OrderParam param) {
                        return param.getOrderId().equals("002")
                    }
                }
        ));
    }

    @Test
    public void findOrderByOrderIdTest() {
        String orderId = "001";
        DemoOrder order = demoService.findOrderByOrderId(orderId);

        assertThat(order.getOrderUser()).isEqualTo("User1");
    }

    @Test
    public void findOrderByOrderParamTest() {
        OrderParam param = new OrderParam();
        param.setOrderId("002");
        DemoOrder order = demoService.findOrderByOrderParam(param);

        assertThat(order.getOrderUser()).isEqualTo("User2"); 
    }
}

与Spring Boot 单元测试笔记相似的内容:

Spring Boot 单元测试笔记

1. 导入JUnit5测试框架 org.springframework.boot spring-boot-starter-test test

SpringBoot中单元测试如何对包含AopContext.currentProxy()的方法进行测试

今天在工作中遇到一个问题,一个Service类中有一个方法,其中使用了 AopContext.currentProxy() 去访问自身的函数,例如 int result = ((OrderServiceImpl) AopContext.currentProxy()).save(); 单元测试方法如下

Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了

如何阻止 Java SpringBoot Test 单元测试中包括多线程时,没跑完就结束了 使用 CountDownLatch CountDownLatch、CyclicBarrier 使用区别 多线程 ThreadPoolTaskExecutor 应用 Java BasePooledObjectF

[EasyExcel] 导出合并单元格

前言 使用spring boot 对excel 进行操作在平时项目中要经常使用。常见通过jxl和poi 的方式进行操作。但他们都存在一个严重的问题就是非常的耗内存。这里介绍一种 Easy Excel 工具来对excel进行操作。 一、Easy Excel是什么? EasyExcel是阿里巴巴开源的一

简单进行Springboot Beans归属模块单元的统计分析方法

简单进行Springboot Beans归属模块单元的统计分析方法 背景 基于Springboot的产品变的复杂之后 启动速度会越来越慢. 公司同事得出一个结论. beans 数量过多会导致启动速度逐渐变慢. 之前同事写过功能进行分析. 但是本着能不影响产品就不影响产品. 我想通过其他方式进行处理.

盘点 Spring Boot 解决跨域请求的几种办法

熟悉 web 系统开发的同学,对下面这样的错误应该不会太陌生。 之所以会出现这个错误,是因为浏览器出于安全的考虑,采用同源策略的控制,防止当前站点恶意攻击 web 服务器盗取数据。 01、什么是跨域请求 同源策略,简单的说就是当浏览器访问 web 服务器资源时,只有源相同才能正常进行通信,即协议、域

Spring Boot应用中如何动态指定数据库,实现不同用户不同数据库的场景

当在 Spring Boot 应用程序中使用Spring Data JPA 进行数据库操作时,配置Schema名称是一种常见的做法。然而,在某些情况下,模式名称需要是动态的,可能会在应用程序运行时发生变化。比如:需要做数据隔离的SaaS应用。 所以,这篇博文将帮助您解决了在 Spring Boot

3分钟带你搞定Spring Boot中Schedule

一、背景介绍 在实际的业务开发过程中,我们经常会需要定时任务来帮助我们完成一些工作,例如每天早上 6 点生成销售报表、每晚 23 点清理脏数据等等。 如果你当前使用的是 SpringBoot 来开发项目,那么完成这些任务会非常容易! SpringBoot 默认已经帮我们完成了相关定时任务组件的配置,

手把手教你解决spring boot导入swagger2版本冲突问题,刘老师教编程

手把手教你解决spring boot导入swagger2版本冲突问题 本文仅为个人理解,欢迎大家批评指错 首先Spring Boot 3 和 Swagger 2 不兼容。在 Spring Boot 3 中,应该使用 Springdoc 或其他与 Spring Boot 3 兼容的 API 文档工具来

一文了解Spring Boot启动类SpringApplication

只有了解 Spring Boot 在启动时都做了些什么,我们才能在后续的实践的过程中更好地理解其运行机制,以便遇到问题能更快地定位和排查。