Springboot使用DBUnit@DatabaSesetup进行单元测试

初入SpringBoot,在项目上写测试感觉都是很自然的事情,没有尝试过自己去搭集成测试的环境,没有关注过编写测试需要引入哪些包,看到别人怎么写自己就跟着怎么写。下项目后自己尝试着去写了一个demo,并且写了对应的测试.这篇文章为本人自己的踩坑日记,无指导作用,使用DBUNIT进行的集成测试,错误之处请多包涵,欢迎指正~!

1.测试环境

testImplementation("org.dbunit:dbunit:2.5.2")
testImplementation("com.github.springtestdbunit:spring-test-dbunit:1.3.0")
testImplementation 'org.springframework.boot:spring-boot-starter-test'
复制代码

DEUNIT官方手册: springtestdbunit.github.io/spring-test…

2.代码

@SpringBootTest
@ContextConfiguration
@TestExecutionListeners({
        DependencyInjectionTestExecutionListener.class,
        DbUnitTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionDbUnitTestExecutionListener.class,
})```
public class StudentRepositoryTest {

    @Autowired
    private StudentRepository studentRepository;

    @Test
    @DatabaseSetup("/dbunit/studentTestSample.xml")
    public void should_get_student_info_id() {

        StudentInfoDo studentInfoDo = studentRepository.findStudentById(1l);

        assertThat(studentInfoDo.getId()).isEqualTo(1l);
        assertThat(studentInfoDo.getStudentId()).isEqualTo("studentId1");
        assertThat(studentInfoDo.getName()).isEqualTo("studentName1");
        assertThat(studentInfoDo.getGender()).isEqualTo(GenderEnum.MALE);
    }
}
复制代码

xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
    <student_info id="1" student_id="studentId1" student_name="studentName1" age="7" gender="MALE" grouped="0" />
</dataset>
复制代码

SpringBootTest这个注解时测试必要的,如果是使用JUNIT4,这里应该还要加上**@RunWith(SpringJUnit4ClassRunner.class)** ,但是在JUnit5(如果引包里面有jupiter就是5)后都整合到了SpringBootTest里面去了

@TestExecutionListeners官方手册中指出,要使用DBUnit要引入DbUnitTestExecutionListener.class以及相关的标准Spring listener配置。关于TransactionDbUnitTestExecutionListener是官方文档中建议的:当你使用Transactional的时候最好引入这个class,他会令事务在databaseSetup之前启动,在databaseteardown之后结束。

ContextConfiguration加载应用程序上下文,可以在用里面配上需要加载的应用程序。这里没有加,个人理解是后用面@Autowired注入了对应的repo实体,这时Spring会去根据这个bean查找其对应的上下文,不需要自己手动配置。

@Autowired注入对应的测试实体

@DatabaseSetup这是SpringDBUnit使用的注解,用于配置数据库文件,Spring使用# com.github.springtestdbunit.dataset.FlatXmlDataSetLoader进行数据库文件的读取。路径中的文件存放了理想测试时所需要用的数据库的数据。默认是xml文件,也可以根据自己的需要在后面指定想要的文件类型读取器。

@DatabaseTearDown注释可用于在测试完成后重置数据库表。 与@DatabaseSetup 一样,注释可以应用于方法或类级别。 使用@DatabaseTearDown 时,以与@DatabaseSetup 相同的方式使用值和类型属性。

@ExpectedDatabase("expectedData.xml")测试完成后,@ExpectedDatabase 注释可用于验证数据库的内容。 当测试执行插入、更新或删除时,通常会使用此注释。可以在单个测试方法或类上应用注释。 在类级别应用时,验证发生在每个测试方法之后。当然,你可以把存入和查询放到一个测试方法中,同时做查询和存入的测试,这样就不需要再去写ExpectedDatabase了。 同时,ExpectedDatabase有两种模式:DatabaseAssertionMode.DEFAULT作为任何标准 DbUnit测试运行,执行预期和实际数据集的完整比较、 DatabaseAssertionMode.NON_STRICT 将忽略未在预期数据集中但存在于实际数据集中的表和列名称。 这在对包含多个具有多列的表的实时数据库执行的集成测试期间很有用。比较推荐使用NON_STRICT模式(实际上不止这两种).

3.我遇到的问题

1.Unable to load dataset from "<filePath>" using class com.github.springtestdbunit.dataset.FlatXmlDataSetLoader](https://stackoverflow.com/questions/70060569/unable-to-load-dataset-from-filepath-using-class-com-github-springtestdbunit)
复制代码

这个问题困扰了我很久,根据去网上寻找的答案,我尝试了如下方法:

  1. 在 @DatabaseSetup路径前面添加classpath
  2. 在xml文件中为每个字段名添加""
  3. 在xml文件中添加版本信息
  4. 采用junit4而不是5
  5. 检查xml文件是不是放在test/resource/对应的路径下
  6. 在github上面搜索spring dbunit demo看别人的demo是怎么写的,一行一行的对比

最后这个问题的原因在于: 我的xml文件没有后缀名xml(我清楚地记得我加了后缀,并且长得也是xml的样子),因此一直找不到这个文件,真是玄学。

在我更改依赖尝试其他方法同时遇到了:

2.cannot find test includes ....
Could not complete execution for Gradle Test Executor
复制代码

用command+,呼出配置框,

image.png 勾选使用IntelliJ IDEA进行测试

复制代码

不行,会报error create bean with studentJpaRepository的错误,这种解决办法不是我们期望的,因为本来就不会再studentJpaRepository里面使用注解.

4.聊聊集成测试

前面用了@ContextConfiguration来加载上下文,而当我们要进行集成测试的时候,期望是对项目启动->接口->service->dao层进行完整的流程,这时候可以使用@SpringApplicationConfiguration它会从启动类加载上下文,并且开启日志,加载外部属性。

.总结

总结一下,很多问题都很晦涩,但是多花时间一定能解决,无论是去网上搜寻答案、提问、实在不行去github上面搜对应的关键词看看别人的demo是怎么写的,一行一行的对比差别在哪里,问题就这样解决,虽然费时,不过要相信最后都能解决,解决的过程中要戒骄戒躁~

猜你喜欢

转载自juejin.im/post/7033598851760013320