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框架一起来看和使用,可以达到事半功倍的效果。代码要练习,光看是不行的,不上手,就看不到输出,就容易忽略一些细节,希望大家都能学的贼溜,明年拿高薪。

目录
相关文章
|
22天前
|
Java API Maven
如何使用Java开发抖音API接口?
在数字化时代,社交媒体平台如抖音成为生活的重要部分。本文详细介绍了如何用Java开发抖音API接口,从创建开发者账号、申请API权限、准备开发环境,到编写代码、测试运行及注意事项,全面覆盖了整个开发流程。
64 10
|
23天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
60 2
|
2天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
31 10
|
5天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
24天前
|
存储 运维 安全
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
38 2
|
28天前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
48 4
|
1月前
|
缓存 监控 Java
如何运用JAVA开发API接口?
本文详细介绍了如何使用Java开发API接口,涵盖创建、实现、测试和部署接口的关键步骤。同时,讨论了接口的安全性设计和设计原则,帮助开发者构建高效、安全、易于维护的API接口。
81 4
|
29天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
35 0
|
Java 开发工具 git
Java开发初级6.24.3
5.在Git使用过程中,进行Git配置的操作命令是哪个() A. config B. config -g C. config -a D. git config 相关知识点: 在git中,经常使用git config 命令用来配置git的配置文件,git配置级别主要有:仓库级别 local 【优先级最高】、用户级别 global【优先级次之】、系统级别 system【优先级最低】 正确答案:D 10.RDBMS是什么? A. Rela Database Management Systems B. Relational Database Management Systems C. Relation
139 0
|
SQL 前端开发 JavaScript
Java开发初级6.24.2
3.Java网站src/main/java目录保存的是什么资源? A. Java源代码文件 B. 测试代码 C. JavaScript、CSS等文件 D. 图片资源 正确答案:A 4.什么是索引Index? A. SQL数据库里的表管理工具 B. SQL数据库里的查询工具 C. SQL数据库里的目录工具 D. SQL数据库用来加速数据查询的特殊的数据结构 正确答案:D
147 0