0

我有 2 个父测试类:

@SpringBootTest(properties = {
        "spring.datasource.url=jdbc:tc:mysql:8.0.25:///my_test_db?TC_INITSCRIPT=db/init_mysql.sql",
        "spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver"
})
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
public abstract class UserApplicationIntegrationTest {
}

@SpringBootTest
@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
public abstract class UserApplicationTest {
}

这个想法是让各种测试类扩展这些类。需要模拟 MySQL 数据库的那些将扩展 UserApplicationIntegrationTest。不需要数据库连接但需要 Spring 上下文的将扩展 UserApplicationTest。

在没有 UserApplicationIntegrationTest 的情况下,所有扩展 UserApplicationTest 的测试类都运行良好,包括使用 Mockito 框架。不幸的是,当我介绍 UserApplicationIntegrationTest 及其子测试(与 dockerised db 实例完美配合)时,这些测试开始失败,因为它们突然需要数据源。

Caused by: org.springframework.boot.autoconfigure.jdbc.DataSourceProperties$DataSourceBeanCreationException: Failed to determine a suitable driver class

如果我尝试在应用程序属性或父类的注释中排除数据源自动配置,则 testcontainers 测试(那些扩展 UserApplicationIntegrationTest)开始失败,因为 Spring 上下文存在问题并且无法在这些测试中再自动装配 bean .

在我知道之前,我已经陷入了一个尝试混乱的排除/添加的兔子洞,这是我以前在以前的项目中遇到过的,它只会导致进一步的问题。

本质上,我希望在我的项目中共存 3 种类型的测试:

  1. 没有 Spring 上下文的单元测试
  2. 使用 Spring 上下文进行单元测试(包括大量模拟但仍然支持自动装配/构造函数注入)
  3. 使用 Spring 上下文进行集成测试,该上下文启动测试容器并允许我测试数据库交互(并可能进行端到端测试)

我想避免为所有 Spring 上下文测试启动 testcontainers 的最初原因(这将“工作”得很好,并且在构建过程中只包括 1 个 docker 延迟)是因为它让我不得不等待 mysql 连接到每次我在开发过程中在本地运行单独的 Spring 上下文测试时都会对实例进行 dockerised。

有没有一种简洁的方法来实现这一目标,或者有一种更好的方法来满足需求?

提前致谢。

4

1 回答 1

0

希望我理解正确,我所做的是实现一个抽象的 TestContainer 测试类:

package de.dwosch.it;

@ActiveProfiles("test")
    @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
    @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
    @ContextConfiguration(initializers = AbstractPostgreSQLTestContainerIT.Initializer.class)
    @Testcontainers
    public abstract class AbstractPostgreSQLTestContainerIT {
        private static final String POSTGRES_VERSION = "postgres:11.1";
        public static PostgreSQLContainer database;
    
        static {
            database = new PostgreSQLContainer(POSTGRES_VERSION);
            database.start();
        }
    
        static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
            @Override
            public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
                TestPropertySourceUtils.addInlinedPropertiesToEnvironment(
                        configurableApplicationContext,
                        "spring.datasource.url=" + database.getJdbcUrl(),
                        "spring.datasource.username=" + database.getUsername(),
                        "spring.datasource.password=" + database.getPassword()
                );
            }
        }
    }

然后我只是通过这个抽象类扩展我的测试类,它将启动一个测试容器和整个 spring 上下文以更好地分离

class MyAwesomeControllerIT extends AbstractPostgreSQLTestContainerIT { }
于 2021-05-19T07:37:04.853 回答