对于 JUnit 测试用例,有没有在内存中运行 MySQL 的方法?

我只是试图为访问 MySQL 数据库的服务添加测试用例,我想重新创建整个模式(对于某些场景,还可以使用带有每个测试用例所需数据的 MySQL 转储文件)。我四处看了看,发现一些家伙使用 SQLite/H2和其他人这样做,但我只是想知道是否有任何方法可以运行 MySQL 内存,所以我不需要担心任何具体的 MySQL 方言,我可能使用我们的服务。

42773 次浏览

这就是为什么使用专有 SQL 扩展通常不是一个好主意的原因之一。

我要做的就是确定使用非标准 SQL 的位置,并重构代码以将这些部分移动到专用服务。然后您可以在运行单元测试时模拟这些。

您可以为 JUnit 测试使用不同的模式。如果您正在使用 Spring,它的 JUnit 扩展允许每个测试在只读事务中运行,因此在测试之后数据库中不会持久存储任何数据。如果您需要测试的初始数据,您可以将所需的数据放在参与事务的 @Before标记方法中。

您可以挂载一个 ramdrive (使用 ImDisk) ,将数据文件复制到其中,然后在 my.cnf 中更改适当的配置后启动 Mysql 服务 单元测试数据库通常很小(为了快速测试,您应该保持它们很小) ,它们通常可以放在一个 ramdrive 中。

您还可以考虑在春季测试中使用事务,而不是在每个测试中重新生成表。

我们的开发团队就是这么做的,而且效果非常好,我们的速度提高了一个数量级。

我们使用 MySQL 和 Flyway 来处理迁移。

对于单元测试和简单的集成测试,我们使用的是带有 MODE=MySQL参数的 h 2内存数据库。Mode=MySQL使 H2DB 能够处理大多数 MySQL 方言。

我们在 Spring 配置中的测试数据源是这样设置的:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" />
</bean>

(如果您不知道 Spring-XML 转换为调用 new BasicDataSource,然后在创建的实例上调用 setDriverClassNamesetUrl)

然后我们在数据源上使用 Flyway 来创建模式,并像对待普通的 MySQL 数据库那样读入:

<bean id="flyway" class="com.googlecode.flyway.core.Flyway" init-method="migrate">
<property name="dataSource" ref="dataSource" />
<property name="cleanOnValidationError" value="false" />
<property name="initOnMigrate" value="true" />
<property name="sqlMigrationSuffix" value=".ddl" />
</bean>

您还可以在 jdbcTemplate 中使用 dataSource bean 并以这种方式运行一些 SQL 脚本,或者使用 <jdbc:initialize-database...>标记运行一些 MySQL 脚本。

使用与 MySQL 完全兼容并且可以在 JUnit 测试用例中使用的内存中数据库的最简单方法是 imho MariaDB4j。 你只需要一个 Gradle (/Maven)依赖项(http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22mariaDB4j%22)和几行代码就可以开始了:

DB database = DB.newEmbeddedDB(3306);
database.start();
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/test", "root", "");

启动脚本可以通过

database.source("path/to/resource.sql");

更多关于 GitHub 的信息: Https://github.com/vorburger/mariadb4j

编辑: 对于这个答案,我有一些提示: MariaDB4j 似乎在系统临时文件夹中添加了文件。所以它将以一种嵌入式的方式工作,这意味着不需要安装任何东西,您只需通过您想要的构建工具使用依赖项。但是它不是一个真正的仅在内存中的解决方案,因此我们不能再谈论单元测试,因为单元测试不能依赖于文件或数据库

我建议使用基于 docker 的 mysql/postgres/DB testContainer。

Pom.xml

    <dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.15.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.15.1</version>
<scope>test</scope>
</dependency>

Java

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("test")
@Testcontainers

应用测试

  datasource:
initialization-mode: always
schema: classpath*:schema-anyDb.sql  #initial sql script to createDB
url: jdbc:tc:postgresql:11.9:///
jpa:
hibernate.ddl-auto: none
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
default_schema: public
show-sql: true