问题描述
我想使用 JUnit 5 将测试容器与 @DataJpaTest
(和 @SpringBoottest
)一起使用。我使用 @Testcontainers
和 @Container
注释进行基本设置,如下所示:
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 org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgresqlContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import static org.assertj.core.api.Assertions.assertthat;
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
public class AtleteRepositoryTest {
@Container
private static final PostgresqlContainer<?> CONTAINER = new PostgresqlContainer<>("postgres:11");
@DynamicPropertySource
static void registerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url",CONTAINER::getJdbcUrl);
registry.add("spring.datasource.username",CONTAINER::getUsername);
registry.add("spring.datasource.password",CONTAINER::getpassword);
}
@Autowired
private AtleteRepository repository;
@Test
void testSave() {
repository.save(new Atlete("Wout Van Aert",1,0));
assertthat(repository.count()).isEqualTo(1);
}
}
有关完整示例代码(https://github.com/wimdeblauwe/blog-example-code/tree/feature/testcontainers-datajpatest/testcontainers-datajpatest、AtleteRepositoryTest 和 TeamRepositoryTest),请参阅 TestcontainersDatajpatestApplicationTests。
为了避免重复声明 Postgresql 容器和动态属性,我尝试了以下操作:
JUnit 5 扩展
Baeldung 有一个关于如何use a JUnit 5 extension to avoid the duplication 的博客。
import org.junit.jupiter.api.extension.AfterallCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.testcontainers.containers.PostgresqlContainer;
public class PostgresqlExtension implements BeforeAllCallback,AfterallCallback {
private PostgresqlContainer<?> postgres;
@Override
public void beforeAll(ExtensionContext context) {
postgres = new PostgresqlContainer<>("postgres:11");
postgres.start();
System.setProperty("spring.datasource.url",postgres.getJdbcUrl());
System.setProperty("spring.datasource.username",postgres.getUsername());
System.setProperty("spring.datasource.password",postgres.getpassword());
}
@Override
public void afterall(ExtensionContext context) {
postgres.stop();
}
}
如果您只有 1 个测试,它会起作用,但如果您同时运行多个测试(使用 IntelliJ 或使用 Maven),则不。在这种情况下,其中一项测试将失败,因为无法建立与数据库的连接。
另请注意,此扩展不使用 DynamicPropertyRegistry
,而是使用普通的环境变量。
查看代码的 feature/testcontainers-datajpatest_baeldung-extension 分支。
使用通用超类
在分支 feature/testcontainers-datajpatest_database-base-test 上,我尝试使用通用超类:
import org.junit.jupiter.api.Afterall;
import org.junit.jupiter.api.BeforeAll;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgresqlContainer;
public class DatabaseBaseTest {
private static final PostgresqlContainer<?> CONTAINER = new PostgresqlContainer<>("postgres:11");
@BeforeAll
static void start() {
CONTAINER.start();
}
@Afterall
static void stop() {
CONTAINER.stop();
}
@DynamicPropertySource
static void registerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url",() -> {
String jdbcUrl = CONTAINER.getJdbcUrl();
System.out.println("jdbcUrl = " + jdbcUrl);
return jdbcUrl;
});
registry.add("spring.datasource.username",CONTAINER::getpassword);
}
}
不幸的是,这也不起作用。我在日志中注意到 @DynamicPropertySource
注释的方法只调用一次,而不是每次测试时调用,这让我尝试了选项 3:
子类中有 @DynamicPropertySource
的公共超类
当使用公共超类,但在每个子类中添加@DynamicPropertySource
方法时,它再次起作用。
此类子类的示例代码:
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class AtleteRepositoryTest extends DatabaseBaseTest {
@DynamicPropertySource
static void registerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url",0));
assertthat(repository.count()).isEqualTo(1);
}
}
请参阅该版本的分支 feature/testcontainers-datajpatest_database-base-test_subclasses。
所以虽然它有效,但每个测试类中仍然有很多重复。
是否有其他选择可以避免重复?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)