spring-boot - @DataJpaTest 在 MySQL 中更新实际数据,但在 H2 中工作正常

标签 spring-boot jpa testing spring-data-jpa integration-testing

我正在学习@DataJpaTest,我的测试用例如下

import com.demo.mockito.entity.StudentEntity;
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 java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class StudentRepositoryTest {
    @Autowired
    private StudentRepository studentRepository;
    @Test
    public void findAll() {
        StudentEntity student1 = new StudentEntity("shrikant", new Date());
        studentRepository.save(student1);
        List<StudentEntity> entityList = studentRepository.findAll();
        assertEquals(1, entityList.size());
    }
}

它给了我错误

expected: <1> but was: <33>
Expected :1
Actual   :33
<Click to see difference>

因为现在数据库中有 33 条记录,并且随着每次保存测试用例,它都会增加。

src/main/test/application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/student_db?jdbcCompliantTruncation=false&sessionVariables=sql_mode='NO_ENGINE_SUBSTITUTION'&useSSL=false&useServerPrepStmts=false&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.generate-ddl=true
spring.jpa.database.schema=student_db
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

构建.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.2.6.RELEASE'
    id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}
group 'com.demo.mockito'
version '1.0-SNAPSHOT'
repositories {
    mavenCentral()
}
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testRuntime('org.junit.jupiter:junit-jupiter-engine:5.2.0')
    runtime 'mysql:mysql-connector-java'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}
test {
    useJUnitPlatform()
}

如果我使用 h2,它会给出正确的结果,因为每次它重新创建一个没有数据的新实例时。

这是预期的行为吗?还是我做错了什么 是数据库测试时的 h2 标准。 但当我的目的只是测试 MySQL 时,我不想在应用程序中配置另一个数据库。

最佳答案

if i use h2 instead, it gives correct result because every time it recreates a new instance with no data.

您自己回答了您的问题。
默认情况下,在每个 Spring Boot 容器启动时(当您使用 @SpringBootTest 或测试切片 @DataJpaTest 注释定义测试时会发生这种情况),会创建一个新的数据库实例当您使用内存数据库,例如 H2(这是您可以更改的 H2 的默认行为),而当您使用 MySQL 时,Spring Boot 默认情况下不使用该策略。它不会更改数据库内容。
The official doc states indeed :

Spring Boot chooses a default value for you based on whether it thinks your database is embedded. It defaults to create-drop if no schema manager has been detected or none in all other cases.

关于:

but I don't want to configure another database in my application when my intention is to test MySQL only.

对于单元测试,您希望使用内存数据库作为 H2,因为这是直接的,并且不需要长/复杂的设置(即填充/清理数据库状态)。
对于集成测试,您希望使用目标数据库(此处为 MySQL),因为您希望编写最接近应用程序行为的测试。 为了实现这一点,您必须使用特定的数据库(测试数据库),您还必须填充测试的夹具数据,最后您必须清理数据以使测试可重现。

这两种测试是互补的。

关于spring-boot - @DataJpaTest 在 MySQL 中更新实际数据,但在 H2 中工作正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61557012/

相关文章:

hibernate - JPA Hibernate 一对多批量插入

java - 如何在jpa中创建InnoDB表?

java - 如何为 Spring Boot 2 添加自定义 MeterRegisty

java - 微服务无法访问 docker-compose 中的配置服务

java - 千分尺与 DynaTrace 的集成

java - 请求/响应对象

java - 在 Hibernate 3 上禁用透明持久化

internet-explorer - 如何在不使用任何虚拟以及第三方工具的情况下在同一台机器上运行多个版本的 IE(IE10、IE11)

python - 假设策略 : for each "bucket", 从桶中取一个值

java - 具有服务器发送事件 (SSE) 支持的模拟库