Spring Boot测试 - 使用Testcontainers进行数据访问层集成测试

x33g5p2x  于2022-02-15 转载在 Spring  
字(4.8k)|赞(0)|评价(0)|浏览(668)

在之前的教程中,我们已经看到了如何使用Testcontainers为REST API编写集成测试。

在本教程中,我们将学习如何使用Testcontainers为数据访问或存储库层编写集成测试。
本教程的完整源代码在我的GitHub资源库中,地址是https://github.com/RameshMF/springboot-testcontainers-demo

好吧,本教程是前一个教程的延续,所以你必须先看如何使用Testcontainers为REST API编写集成测试的教程。

**如果你想学习更多关于Spring boot测试的知识,那么强烈建议你学习我的Udemy课程。 **Testing Spring Boot Application with JUnit and Mockito (Includes Testcontainers)

为数据访问或存储层与MySQL数据库创建集成测试

让我们先为StudentRepository编写集成测试,不使用Testcontainers,然后再使用Testcontainers。

让我们创建StudentRepositoryTests类,并向其添加以下内容。

package net.javaguides.spirngboot.repository;

import net.javaguides.spirngboot.AbstractContainerBaseTest;
import net.javaguides.spirngboot.entity.Student;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class StudentRepositoryTest {

    @Autowired
    private StudentRepository studentRepository;

    // JUnit for save student operation - BDD style
    @Test
    public void givenStudentObject_whenSave_thenReturnSavedStudent(){

        // given - setup or precondition
        Student student = Student.builder().firstName("Ramesh")
                .lastName("fadatare").email("ramesh@gmail.com").build();

        // when - action or the testing
        Student savedStudent = studentRepository.save(student);

        // then - very output
        Assertions.assertNotNull(savedStudent);
        Assertions.assertNotNull(savedStudent.getId());

    }

    // JUnit for findById student operation - BDD style
    @Test
    public void givenStudentId_whenfindbyId_thenReturnSavedStudent(){

        // given - setup or precondition
        Student student = Student.builder().firstName("Ramesh")
                .lastName("fadatare").email("ramesh@gmail.com").build();
        Student savedStudent = studentRepository.save(student);

        // when - action or the testing
        Student studentDB = studentRepository.findById(student.getId()).get();

        // then - very output
        Assertions.assertNotNull(studentDB);
    }

}

Spring boot提供了@DataJpaTest注解。这个注解将禁用完全的自动配置,而只应用与JPA测试相关的配置。默认情况下,它将使用一个嵌入式内存H2数据库,而不是在配置文件中声明的数据库,与磁盘文件数据库相比,测试运行时间更快。

请注意,我们已经使用@AutoConfigureTestDatabase注解禁用了H2内存数据库支持,因为我们想用MySQL数据库运行集成测试。

我们已经在Spring boot项目中配置了MySQL数据库,所以让我们用MySQL数据库运行集成测试。

运行集成测试

我们所写的集成测试有什么问题?

在编写集成测试时,一个常见的问题是对集成测试应该运行的已安装组件(例如:MySQL、RabbitMQ)的依赖性。

在我们的案例中,我们的集成测试依赖于 MySQL 数据库。 在集成测试要运行的每台机器上安装特定版本的MySQL数据库需要很多时间。

基本上,我们的集成测试依赖于外部服务(安装MySQL、Rabbit MQ、Redis等)来运行集成测试,那么如何减少这种依赖性--什么将是解决方案。

解决方案是Testcontainers.

什么是Testcontainers,以及它是如何解决我们在之前的教程中已经讨论过的问题的。 

Testcontainers是一个支持JUnit测试的Java库,为普通数据库、Selenium网络浏览器或其他可以在Docker容器中运行的东西提供轻量级的、可抛弃的实例。

Testcontainer允许我们在测试中使用Docker容器。因此,我们可以编写依赖于外部资源的独立的集成测试。

##使用Testcontainers为数据访问或存储库层编写集成测试

让我们改变集成测试来使用Testcontainers。

我们只需要用AbstractContainerBaseTest类扩展我们的StudentRepositoryTest类。

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class StudentRepositoryTest extends AbstractContainerBaseTest {
 // code goes here
}

下面是完整的代码。

package net.javaguides.spirngboot.repository;

import net.javaguides.spirngboot.AbstractContainerBaseTest;
import net.javaguides.spirngboot.entity.Student;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import static org.junit.jupiter.api.Assertions.*;

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class StudentRepositoryTest extends AbstractContainerBaseTest {

    @Autowired
    private StudentRepository studentRepository;

    // JUnit for save student operation - BDD style
    @Test
    public void givenStudentObject_whenSave_thenReturnSavedStudent(){

        // given - setup or precondition
        Student student = Student.builder().firstName("Ramesh")
                .lastName("fadatare").email("ramesh@gmail.com").build();

        // when - action or the testing
        Student savedStudent = studentRepository.save(student);

        // then - very output
        Assertions.assertNotNull(savedStudent);
        Assertions.assertNotNull(savedStudent.getId());

    }

    // JUnit for save student operation - BDD style
    @Test
    public void givenStudentId_whenfindbyId_thenReturnSavedStudent(){

        // given - setup or precondition
        Student student = Student.builder().firstName("Ramesh")
                .lastName("fadatare").email("ramesh@gmail.com").build();
        Student savedStudent = studentRepository.save(student);

        // when - action or the testing
        Student studentDB = studentRepository.findById(student.getId()).get();

        // then - very output
        Assertions.assertNotNull(studentDB);
    }

}

请注意,我们在前面的教程中已经用Testcontainers逻辑创建了AbstractContainerBaseTest

使用Testcontainers运行集成测试

GitHub存储库

本教程的完整源代码在我的GitHub仓库,地址是https://github.com/RameshMF/springboot-testcontainers-demo

相关文章