Java开发 - Spring Test知多少?

简介: 在前文中,我们也使用了测试代码来进行简单的单元测试,但是我们会发现,里面有大量的重复代码,实际给我们的体验并不是太好,所以这篇,我们来学习Spring Test,Spring Test不仅仅限于在Mybatis框架,只要是基于Spring的框架的都可以使用Spring Test,使用Spring Test,将给测试模块带来质的改善,大大提高了自测的效率。接下来,我们就来学习Spring Test的用法和注意事项吧。

前言

在前文中,我们也使用了测试代码来进行简单的单元测试,但是我们会发现,里面有大量的重复代码,实际给我们的体验并不是太好,所以这篇,我们来学习Spring Test,Spring Test不仅仅限于在Mybatis框架,只要是基于Spring的框架的都可以使用Spring Test,使用Spring Test,将给测试模块带来质的改善,大大提高了自测的效率。接下来,我们就来学习Spring Test的用法和注意事项吧。

Spring Test的作用

在普通测试环境下,我们在使用Spring的时候,需要手动加载Spring配置,手动从Spring容器中获取对象,前文中的使用全是如此,这也就违背了我们使用Spring框架的意愿:自动创建对象,自动管理对象。我们把这种用法叫自动装配。

Spring还有一个用处,使用@Sql注解,此注解可在测试类方法之前定义,提前或延后执行某段sql语句,在测试中也经常使用。

在项目中加入Spring Test

添加依赖

<!--Spring Test依赖-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.14</version>
        </dependency>

Spring Test无法单独工作,仍需配合其他测试依赖项和其他Spring依赖一起使用,可参照Mybatis一文中的依赖进行添加,亦可在原项目中直接操作。但要注意,要和其他Spring依赖项的版本保持一致,切记。

创建测试类

package cn.codingfire.mybatis;
public class MybatisTest {
}

此时需在测试类上添加@SpringJUnitConfig注解:

package cn.codingfire.mybatis;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(SpringConfig.class)
public class MybatisTest {
}

接着我们可以在此类中添加Spring的配置类,这样,在此类中任何方法之前,都会先加载Spring的配置类,Spring容器中存在的类就都可以实现自动装配了。我们以环境变量为例:

package cn.codingfire.mybatis;
import cn.codingfire.mybatis.config.SpringConfig;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
@SpringJUnitConfig(SpringConfig.class)
public class MybatisTest {
    @Autowired
    Environment env;
    @Test
    public void testEnvironment() {
        System.out.println(env.getProperty("datasource.url"));
        System.out.println(env.getProperty("datasource.driver"));
        System.out.println(env.getProperty("datasource.username"));
        System.out.println(env.getProperty("datasource.password"));
    }
}

接着运行此测试方法,查看输出:

编辑

已经成功输出了我们在properties文件中配置的信息。对比之前Mybatis中的测试方法如下:

@Test
    public void loadBasicInfo() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        ConfigurableEnvironment environment = ac.getEnvironment();
        System.out.println(environment.getProperty("datasource.url"));
        System.out.println(environment.getProperty("datasource.driver"));
        System.out.println(environment.getProperty("datasource.username"));
        System.out.println(environment.getProperty("datasource.password"));
        ac.close();
    }

先获取ac,再获取environment,最后再关闭ac,简化了太多步骤。使用Spring Test,我们只需关注测试的内容本身,而不用去管环境的问题,效果要更好。再增删改查时也不需要再关注开头和结尾的那几段代码,这种重复性的操作被省略,也是自动装配的精髓之一。

关于@Autowired注解,就是自动装配的意思,我们可以尝试着给其他的对象添加此注解:

编辑

会看到AdminMapper报一个错,这里有个小知识点。这是因为编译器问题导致无法识别,解决办法是在AdminMapper的类中添加@Repository注解,回来后再看,正常来说报错会消失,但有的人的不会消失,可在注解里添加required属性为false:

编辑

此时,问题已经解决了,它的意思是,能装配上就装,不能装配也不强求。有意思的是,即使你不管这个报错,方法也可正常运行,不存在任何影响。

Spring Test下的测试方法

我们以插入方法为例,做个前后对比。

未使用Spring Test的插入方法测试:

@Test
    public void testInsert() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
        AdminMapper adminMapper = ac.getBean(AdminMapper.class);
        Admin admin = new Admin();
        admin.setUsername("admin04");
        admin.setPassword("123456");
        adminMapper.insert(admin);
        ac.close();
    }

使用了Spring Test的插入方法测试 :

@Test
    public void testInsert() {
        Admin admin = new Admin();
        admin.setUsername("admin04");
        admin.setPassword("123456");
        adminMapper.insert(admin);
    }

前后对比明显,自动装配后,adminMapper由系统创建管理,可在类中直接使用,简化了代码。

@Sql注解

@Sql注解的作用和注意事项

Spring Test测试类中,还可以使用@Sql注解,他可以加载某些脚本.sql的脚本,可以在测试前后执行一些给定的sql语句。它的作用是可以在测试时进行反复测试,在Mybatis中,我们在测试时,有时为了使mapper的方法运行成功,需要运行插入的方法,这就很不友好了,增加了测试的成本,比如我删除某条数据后,表中没有数据,我要再执行删除操作前,必须要再插入一条数据,否则会报错,而我使用@Sql注解,就可以解决这个问题,使得每次测试不需要再关注其他的方法。

使用此注解要注意几个问题:

  • @Sql注解可以添加在单独的方法中,仅对此方法有效,也可添加在测试类上,对类中所有的方法有效。如果类和方法上都添加了相同的@Sql注解,仅方法上的生效
  • 可方法前执行.sql脚本,也可方法后执行.sql脚本,通过executionPhase属性来管理
  • @Sql注解可添加多个

@Sql注解怎么用

首先,我们需要先创建一个.sql文件,选择file,创建一个truncate.sql:

编辑

在test下的resoutces文件中创建,在此文件中可以看到和再sql工具中一样,是有sql提醒的。 truncate的意思是截断,在sql中意味着清空整张表。我们知道,数据库表中不允许插入相同的两条数据,否则就会报重复的错误,使用此注解,在每次插入前都清空整张表就可以频繁测试,看代码:

@Sql(scripts = {"classpath:truncate.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
    @Test
    public void testInsert() {
        Admin admin = new Admin();
        admin.setUsername("admin04");
        admin.setPassword("123456");
        adminMapper.insert(admin);
    }

可以在插入前清空整张表,以达到频繁插入的测试。

以删除为例,我们想删除的时候数据库表中一直有数据。此时,也可以使用此注解,接下来我们来说说怎么同时使用多个.sql脚本,首先创建一个插入的.sql脚本:

编辑

看代码:

@Sql(scripts = {"classpath:truncate.sql", "classpath:insert.sql"})
    @Test
    public void testDelete() {
        adminMapper.deleteById(1L);
    }

每次执行次方法都是成功的。如果你想在方法执行后再执行某些sql的话,可以设置@Sql的executionPhase属性为Sql.ExecutionPhase.AFTER_TEST_METHOD:

executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD

断言

我们通常在测试类中使用Assertions类的静态方法对测试结果进行预测,帮助我们发现代码中可能存在的问题,一旦不符合预测的正确结果就会报错,大大提高代码的正确性。常用的一些断言方法有:

  • assertEquals():断言匹配(相等)
  • assertNotEquals():断言不匹配(不相等)
  • assertTrue():断言为“真”
  • assertFalse():断言为“假”
  • assertNull():断言为null
  • assertNotNull():断言不为null
  • assertThrows():断言抛出异常
  • assertDoesNotThrow():断言不会抛出异常
  • 其他

接下来我们挑几个在代码中来看使用效果。

assertEquals():

@Sql(scripts = {"classpath:truncate.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
    @Test
    public void testInsert() {
        Admin admin = new Admin();
        admin.setUsername("admin04");
        admin.setPassword("123456");
        int index = adminMapper.insert(admin);
        System.out.println(index);
        Assertions.assertEquals(1,index);
    }

Assertions.assertEquals 有两个参数,第一个是expected,是期望的值,第二个是ectual,是实际的值,如果预测的不对,就会报错,正确则没有任何反应。

assertTrue()

还以插入为例,看代码:

@Sql(scripts = {"classpath:truncate.sql"}, executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
    @Test
    public void testInsert() {
        Admin admin = new Admin();
        admin.setUsername("admin04");
        admin.setPassword("123456");
        int index = adminMapper.insert(admin);
        System.out.println(index);
        boolean isThanZero = index > 0 ? true : false;
        Assertions.assertTrue(isThanZero);
    }

断言isThanZero,即影响的行数大于0,则说明插入成功,否则将报异常。

assertNull()

以根据id获取数据为例:

@Test
    public void getById() {
        Admin admin = adminMapper.getById(10L);
        Assertions.assertNull(admin);
    }

id为10的数据表中没有,所以语言admin为null,是正确的,符合我们的预期,不会报错。

assertThrows()

前面我们说过重复插入数据会把哦重复插入的异常,这时就不能在插入前清空表了,我们以此为例,看代码:

@Test
    public void testInsert() {
        Admin admin = new Admin();
        admin.setUsername("admin04");
        admin.setPassword("123456");
        Assertions.assertThrows(DuplicateKeyException.class, () -> {
            adminMapper.insert(admin);
        });
    }

正常来说,连续执行两次,就会抛出重复插入的异常,但是我们做了断言后,就不会有任何输出,反而会在第一次执行时抛出下面这段异常:

org.opentest4j.AssertionFailedError: Expected org.springframework.dao.DuplicateKeyException to be thrown, but nothing was thrown.

意思是说,我们预测会抛出重复的异常,但是什么也没有抛出。这是正常的,因为第一次插入成功了。

到这里,断言就写完了,上面列出来的每一类中的一个都给出了案例 ,照葫芦画瓢,对另一个取反就是另一个,相信聪明如大家已经知道该怎么用了,不再赘述。

结语

最近几天,这篇算是最短的了,写起来也最省劲,用了不到半天就写完了,虽然简单,但是里面的知识却很重要,最好结合前面的SSM框架一起来看和使用,可以达到事半功倍的效果。代码要练习,光看是不行的,不上手,就看不到输出,就容易忽略一些细节,希望大家都能学的贼溜,明年拿高薪。

目录
相关文章
|
19天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
38 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
3天前
|
XML JSON Java
Spring Boot 开发中常见的错误
本文总结了 Java 开发中常见的几个问题及其改进方法,包括:1. 过度使用 `@Component` 注解;2. `@ResponseBody` 注解的错误用法;3. `@Autowired` 的不当使用;4. `application.properties` 管理不善;5. 异常处理不当。每部分详细解释了错误情况和建议的改进方案,并提供了相应的代码示例。
31 11
|
6天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
52 13
|
3天前
|
IDE Java 测试技术
互联网应用主流框架整合之Spring Boot开发
通过本文的介绍,我们详细探讨了Spring Boot开发的核心概念和实践方法,包括项目结构、数据访问层、服务层、控制层、配置管理、单元测试以及部署与运行。Spring Boot通过简化配置和强大的生态系统,使得互联网应用的开发更加高效和可靠。希望本文能够帮助开发者快速掌握Spring Boot,并在实际项目中灵活应用。
23 5
|
1天前
|
前端开发 Java 开发者
这款免费 IDEA 插件让你开发 Spring 程序更简单
Feign-Helper 是一款支持 Spring 框架的 IDEA 免费插件,提供 URL 快速搜索、Spring Web Controller 路径一键复制及 Feign 与 Controller 接口互相导航等功能,极大提升了开发效率。
|
11天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
44 10
|
5天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
40 2
|
14天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
8天前
|
XML Java 数据格式
Spring Boot 开发中的常见失误
本文深入分析了Spring Boot开发中常见的失误,包括不当使用@Component、@ResponseBody、@Autowired注解,以及不良的异常处理和日志记录实践,提供了有效的规避策略,帮助开发者提升代码质量和系统性能。
|
4月前
|
安全 前端开发 Java
随着企业应用复杂度提升,Java Spring框架以其强大与灵活特性简化开发流程,成为构建高效、可维护应用的理想选择
随着企业应用复杂度提升,Java Spring框架以其强大与灵活特性简化开发流程,成为构建高效、可维护应用的理想选择。依赖注入使对象管理交由Spring容器处理,实现低耦合高内聚;AOP则分离横切关注点如事务管理,增强代码模块化。Spring还提供MVC、Data、Security等模块满足多样需求,并通过Spring Boot简化配置与部署,加速微服务架构构建。掌握这些核心概念与工具,开发者能更从容应对挑战,打造卓越应用。
47 1