여러 Spring Boot 간에 테스트컨테이너를 재사용하는 방법테스트?
Spring Boot에서 Test Containers를 사용하여 다음과 같은 저장소의 유닛 테스트를 실행하고 있습니다.
@Testcontainers
@ExtendWith(SpringExtension.class)
@ActiveProfiles("itest")
@SpringBootTest(classes = RouteTestingCheapRouteDetector.class)
@ContextConfiguration(initializers = AlwaysFailingRouteRepositoryShould.Initializer.class)
@TestExecutionListeners(listeners = DependencyInjectionTestExecutionListener.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Tag("docker")
@Tag("database")
class AlwaysFailingRouteRepositoryShould {
@SuppressWarnings("rawtypes")
@Container
private static final PostgreSQLContainer database =
new PostgreSQLContainer("postgres:9.6")
.withDatabaseName("database")
.withUsername("postgres")
.withPassword("postgres");
하지만 지금은 14개의 테스트가 있으며 매번 테스트가 실행될 때마다 Postgres의 새로운 인스턴스가 가속됩니다.모든 테스트에서 동일한 인스턴스를 재사용할 수 있습니까?모든 테스트가 새로운 애플리케이션을 시작하기 때문에 싱글턴 패턴은 도움이 되지 않습니다.
도 ★★★★★★★★★★★★★★★★★★★★★★★★★testcontainers.reuse.enable=true
.testcontainers.properties
★★★★★★★★★★★★★★★★★」.withReuse(true)
을 사용법
주피터 JUnit은 수 .@Container
재사용 가능한 컨테이너를 원할 경우.이 주석을 사용하면 각 테스트 후 용기가 중지됩니다.
필요한 것은 싱글톤 컨테이너 접근법이며, 예를 들어 다음과 같이 사용합니다. @BeforeAll
컨테이너를 기동합니다., 「 」를 가지고 있어도, 「 」가 됩니다..start()
에서 Testcontainer를 을 선택한 는 새 .withReuse(true)
및 항목에서 사용할 수 있습니다..testcontainers.properties
디렉토리의 : "파일":
testcontainers.reuse.enable=true
간단한 예는 다음과 같습니다.
@SpringBootTest
public class SomeIT {
public static GenericContainer postgreSQLContainer = new PostgreSQLContainer().
withReuse(true);
@BeforeAll
public static void beforeAll() {
postgreSQLContainer.start();
}
@Test
public void test() {
}
}
기타 통합 테스트:
@SpringBootTest
public class SecondIT {
public static GenericContainer postgreSQLContainer = new PostgreSQLContainer().
withReuse(true);
@BeforeAll
public static void beforeAll() {
postgreSQLContainer.start();
}
@Test
public void secondTest() {
}
}
현재 이에 대한 문서를 추가하는 PR이 있습니다.
테스트 용기로 용기를 재사용하는 방법을 자세히 설명하는 블로그 투고를 작성했습니다.
싱글톤 패턴으로 진행하기로 결정한 경우, "JDBC URL 체계를 통해 시작된 데이터베이스 컨테이너"의 경고에 유의하십시오.싱글톤 패턴을 사용했는데도 항상 다른 포트에 매핑된 추가 컨테이너가 생성된다는 것을 알아차릴 때까지 몇 시간이 걸렸습니다.
를 들어, JDBC(호스트리스) URI는 사용하지 말아 주세요.jdbc:tc:postgresql:<image-tag>:///<databasename>
singleton 패턴을 사용합니다.
인정된 답변은 훌륭하지만 문제는 각 통합 테스트에 대해 구성(작성, 시작 등)을 반복해야 한다는 것입니다.보다 적은 코드 행으로 심플한 설정을 실시하는 것이 좋습니다.클린버전은 JUnit 5 확장자를 사용하는 것 같아요.
이렇게 해서 문제를 풀었어요.아래 샘플은 MariaDB 컨테이너를 사용하지만 이 개념은 모든 사용자에게 적용됩니다.
- 컨테이너 구성 홀딩 클래스를 만듭니다.
public class AppMariaDBContainer extends MariaDBContainer<AppMariaDBContainer> {
private static final String IMAGE_VERSION = "mariadb:10.5";
private static final String DATABASE_NAME = "my-db";
private static final String USERNAME = "user";
private static final String PASSWORD = "strong-password";
public static AppMariaDBContainer container = new AppMariaDBContainer()
.withDatabaseName(DATABASE_NAME)
.withUsername(USERNAME)
.withPassword(PASSWORD);
public AppMariaDBContainer() {
super(IMAGE_VERSION);
}
}
- 를 만들고 합니다.
DataSource
。에 따라 :" " " " 라요라라 。
public class DatabaseSetupExtension implements BeforeAllCallback {
@Override
public void beforeAll(ExtensionContext context) {
AppMariaDBContainer.container.start();
updateDataSourceProps(AppMariaDBContainer.container);
//migration logic here (if needed)
}
private void updateDataSourceProps(AppMariaDBContainer container) {
System.setProperty("spring.datasource.url", container.getJdbcUrl());
System.setProperty("spring.datasource.username", container.getUsername());
System.setProperty("spring.datasource.password", container.getPassword());
}
}
- 더하다
@ExtendWith
당신의 시험반으로
@SpringBootTest
@ExtendWith(MariaDBSetupExtension.class)
class ApplicationIntegrationTests {
@Test
void someTest() {
}
}
다른 테스트
@SpringBootTest
@ExtendWith(MariaDBSetupExtension.class)
class AnotherIntegrationTests {
@Test
void anotherTest() {
}
}
싱글톤 컨테이너 또는 재사용 가능한 컨테이너를 사용하는 것이 가능한 해결책이지만, 컨테이너의 라이프 사이클을 애플리케이션 컨텍스트의 라이프 사이클에 적용하지 않기 때문에 둘 다 그다지 이상적이지 않습니다.
단, 컨테이너를 어플리케이션콘텍스트의 라이프 사이클까지 확장하려면ContextCustomizerFactory
블로그 투고에 좀 더 자세히 써놨어요.
테스트 사용 시:
@Slf4j
@SpringBootTest
@EnabledPostgresTestContainer
class DemoApplicationTest {
@Test
void contextLoads() {
log.info("Hello world");
}
}
그런 다음 에서 주석을 활성화합니다.META-INF/spring.factories
:
org.springframework.test.context.ContextCustomizerFactory=\
com.logarithmicwhale.demo.EnablePostgresTestContainerContextCustomizerFactory
다음과 같이 구현할 수 있습니다.
public class EnablePostgresTestContainerContextCustomizerFactory implements ContextCustomizerFactory {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface EnabledPostgresTestContainer {
}
@Override
public ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) {
if (!(AnnotatedElementUtils.hasAnnotation(testClass, EnabledPostgresTestContainer.class))) {
return null;
}
return new PostgresTestContainerContextCustomizer();
}
@EqualsAndHashCode // See ContextCustomizer java doc
private static class PostgresTestContainerContextCustomizer implements ContextCustomizer {
private static final DockerImageName image = DockerImageName
.parse("postgres")
.withTag("14.1");
@Override
public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
var postgresContainer = new PostgreSQLContainer<>(image);
postgresContainer.start();
var properties = Map.<String, Object>of(
"spring.datasource.url", postgresContainer.getJdbcUrl(),
"spring.datasource.username", postgresContainer.getUsername(),
"spring.datasource.password", postgresContainer.getPassword(),
// Prevent any in memory db from replacing the data source
// See @AutoConfigureTestDatabase
"spring.test.database.replace", "NONE"
);
var propertySource = new MapPropertySource("PostgresContainer Test Properties", properties);
context.getEnvironment().getPropertySources().addFirst(propertySource);
}
}
}
어떻게 된 건지 모르겠어@Testcontainers
효과는 있지만 수업당 효과가 있을 것 같습니다.
싱글톤 패턴에 설명된 대로 싱글톤을 정전기 상태로 만들어 신호기 홀더에서 모든 테스트에서 가져오기만 하면 됩니다. 모든 테스트 클래스에서 정의하지 마십시오.
언급URL : https://stackoverflow.com/questions/62425598/how-to-reuse-testcontainers-between-multiple-springboottests
'programing' 카테고리의 다른 글
Angular에 사용자 지정 유효성 검사를 추가하는 방법JS폼? (0) | 2023.03.18 |
---|---|
모든 플러그인이 이미 업데이트되어 있는 경우 WordPress에 플러그인 업데이트가 1개 있음을 표시함 (0) | 2023.03.18 |
메서드 매개 변수에서 WCF webHttpBinding 오류가 발생했습니다."래퍼 요소 없이 최대 하나의 본문 매개 변수를 직렬화할 수 있습니다." (0) | 2023.03.13 |
Woocommerce, 현재 제품 ID 가져오기 (0) | 2023.03.13 |
리스트/어레이가 유효한 JSON입니까? (0) | 2023.03.13 |