【问题标题】:How to embed in memory MariaDB4j to replace default Spring DataSource in JUnit Tests?如何嵌入内存 MariaDB4j 以替换 JUnit 测试中的默认 Spring DataSource?
【发布时间】:2019-02-06 14:43:01
【问题描述】:

我正在为Service 编写测试,该测试使用多个 Jpa 数据存储库。问题是某些存储库使用大量具有MySQL 特定功能的本机查询,例如str_to_date()。因此,当我尝试使用H2 测试服务的方法时,我收到一条错误消息,提示 H2 无法识别功能。我曾尝试在 MySQL 模式下使用 H2,但得到了同样的错误。

heremariaDB4j 被提议作为一种解决方法。我已将依赖项添加到 Maven

<dependency>
    <groupId>ch.vorburger.mariaDB4j</groupId>
    <artifactId>mariaDB4j</artifactId>
    <version>2.3.0</version>
    <scope>test</scope>
</dependency>

但是得到IllegalStateException : Failed to replace DataSource with an embedded database for tests. If you want an embedded database please put a supported one on the classpath or tune the replace attribute of @AutoConfigureTestDatabase

我的测试文件是这样的:

@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.ANY)
public class TestPay {

    @TestConfiguration
    static class PaymentServiceTestContextConfiguration {
        @Bean
        public PaymentService paymentService(){
            return new PaymentService();
        }
    }

    @Autowired
    private PaymentService paymentService;
    @Autowired
    private TarifRepository firstRepository;
    @Autowired
    private BuildingRepository secondRepository;
    @Autowired
    private ApartmentRepository thirdRepository;

    /* Test cases here*/
}

该项目是使用注释驱动的 Spring Boot 构建的。

【问题讨论】:

  • 对测试的简单评论,包括外部来源的 IMO 单元测试可能会变得脆弱。单元测试的目的是确保你的代码在做它应该做的事情。如果您可以通过模拟您的数据库而不是使用内存中的数据库来实现这一点,我会这样做。显然,这取决于您的团队和组织他们喜欢什么,这只是我的 2 美分。
  • 恕我直言,在 JUnit 测试中测试尽可能多的集成是很有意义的,而不仅仅是严格意义上的单元测试。但实际上,这是一个“两个人 - 三个意见”的话题,我们应该在这里停止讨论...... ;-)

标签: java spring junit spring-data-jpa spring-test


【解决方案1】:

我构建了以下类,我在每个需要对mariadb 进行数据库访问的集成测试中重复使用该类。它可能会得到改进(我很乐意提出建议),但到目前为止它仍然有效:

@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource(locations="classpath:application-junit.properties")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) //otherwise mariadb is not cleaned up between tests
public abstract class MyIntegrationTest {

    private static MariaDB4jSpringService DB;

    @BeforeClass
    public static void init() throws ManagedProcessException {
        DB = new MariaDB4jSpringService();
        DB.setDefaultPort(1234);
        DB.start();
        DB.getDB().createDB("yourtables");
        DB.getDB().source("schema.sql"); // init scripts from /src/test/resources/schema.sql
    }

    @AfterClass
    public static void cleanup() {
        if (DB != null) DB.stop();
    }
}

应用程序-junit.properties:

spring.datasource.url=jdbc:mariadb://localhost:1234/yourtables
spring.datasource.username=root
spring.datasource.password=

【讨论】:

  • 我们如何将源从 /src/test/resources/schema.sql 更改为外部目录?
【解决方案2】:

听起来您需要明确声明您的DataSource 以进行测试。在 h2 的情况下,可能已经有一个由 spring 测试依赖声明的数据源 bean,但可能没有 ch.vorburger.mariaDB4j 提供的现成的。

这是我从 elsewhere on the internet 窃取的嵌入式 MariaDB 数据源的示例

import ch.vorburger.mariadb4j.DBConfigurationBuilder
import ch.vorburger.mariadb4j.springframework.MariaDB4jSpringService
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile

import javax.sql.DataSource

@Configuration
@Profile(['local', 'integrationTest'])
class EmbeddedMariaDbConfig {

    @Bean
    MariaDB4jSpringService mariaDB4jSpringService() {
        new MariaDB4jSpringService()
    }

    @Bean
    DataSource dataSource(MariaDB4jSpringService mariaDB4jSpringService,
                          @Value('${app.mariaDB4j.databaseName}') String databaseName,
                          @Value('${spring.datasource.username}') String datasourceUsername,
                          @Value('${spring.datasource.password}') String datasourcePassword,
                          @Value('${spring.datasource.driver-class-name}') String datasourceDriver) {
        //Create our database with default root user and no password
        mariaDB4jSpringService.getDB().createDB(databaseName)

        DBConfigurationBuilder config = mariaDB4jSpringService.getConfiguration()

        DataSourceBuilder
                .create()
                .username(datasourceUsername)
                .password(datasourcePassword)
                .url(config.getURL(databaseName))
                .driverClassName(datasourceDriver)
                .build();
    }
}

【讨论】:

    猜你喜欢
    • 2020-01-17
    • 1970-01-01
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 2013-05-29
    相关资源
    最近更新 更多