为什么 Spring Boot 使用单例容器方法生成 2 个测试容器?
Why does Spring Boot spawn 2 test containers with singleton container approach?
我正在使用 Spring-boot 2.5.3 和 Junit 5
我正在尝试使用 PostgresSQL 测试容器进行测试。我需要将同一个测试容器与集成测试和存储库测试一起使用,因为它在 Docker.
中有两个实例
这是我的基础class,我在这里初始化容器。
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
public class PostgresTestContainer {
static final PostgreSQLContainer postgreSQLContainer;
static {
postgreSQLContainer = (PostgreSQLContainer) new PostgreSQLContainer("postgres:12")
.withDatabaseName("test")
.withUsername("postgres")
.withPassword("postgres")
.withReuse(true);
postgreSQLContainer.start();
}
@DynamicPropertySource
static void datasourceConfig(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
}
}
这是存储库测试。
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class CustomerRepositoryTest extends PostgresTestContainer {
@Autowired
private CustomerRepository customerRepository;
@Test
@Sql("/scripts/import.sql")
public void findAllShouldGetAllCustomers() {
List<Customer> foundCustomers = customerRepository.findAll();
assertThat(foundCustomers).isNotNull();
assertThat(foundCustomers.size()).isEqualTo(3);
}
}
这是我需要使用相同测试容器的另一个地方。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BasicIT extends PostgresTestContainer {
@Autowired
private TestRestTemplate testRestTemplate;
@MockBean
private CustomerRepository customerRepository;
@Test
void shouldFailFetchingCustomersWhenDatabaseIsDown() {
when(customerRepository.findAll()).thenThrow(new RuntimeException("Cannot connect to database."));
ResponseEntity<String> result = this.testRestTemplate
.exchange("/api/v1/customers", HttpMethod.GET, HttpEntity.EMPTY, String.class);
assertEquals(500, result.getStatusCodeValue());
}
@Test
public void shouldFetchAListOfCustomers(){
ResponseEntity<List<Customer>> result = this.testRestTemplate
.exchange("/api/v1/customers", HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference<>() {});
assertEquals(200, result.getStatusCodeValue());
}
}
运行:
mvn clean install
这有效,并且所有测试 运行。
但它会打开两个容器,如此处的 Docker 图片所示。
如何正确使用单例容器?我只想使用一个。
从容器镜像名称可以看出,容器是不同的。第二个容器是您的数据库 (postgres
),但第一个 (ryuk
) 是辅助容器,默认情况下由 Testcontainer
库本身启动。 Ryuk
在不再需要其他容器 (documentation) 后执行故障安全清理。无需担心,因为它很小 (~5Mb)。
如果你绝对确定你不需要它,你可以在this instruction.
之后禁用ryuk
我正在使用 Spring-boot 2.5.3 和 Junit 5
我正在尝试使用 PostgresSQL 测试容器进行测试。我需要将同一个测试容器与集成测试和存储库测试一起使用,因为它在 Docker.
中有两个实例这是我的基础class,我在这里初始化容器。
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
public class PostgresTestContainer {
static final PostgreSQLContainer postgreSQLContainer;
static {
postgreSQLContainer = (PostgreSQLContainer) new PostgreSQLContainer("postgres:12")
.withDatabaseName("test")
.withUsername("postgres")
.withPassword("postgres")
.withReuse(true);
postgreSQLContainer.start();
}
@DynamicPropertySource
static void datasourceConfig(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgreSQLContainer::getJdbcUrl);
registry.add("spring.datasource.password", postgreSQLContainer::getPassword);
registry.add("spring.datasource.username", postgreSQLContainer::getUsername);
}
}
这是存储库测试。
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class CustomerRepositoryTest extends PostgresTestContainer {
@Autowired
private CustomerRepository customerRepository;
@Test
@Sql("/scripts/import.sql")
public void findAllShouldGetAllCustomers() {
List<Customer> foundCustomers = customerRepository.findAll();
assertThat(foundCustomers).isNotNull();
assertThat(foundCustomers.size()).isEqualTo(3);
}
}
这是我需要使用相同测试容器的另一个地方。
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class BasicIT extends PostgresTestContainer {
@Autowired
private TestRestTemplate testRestTemplate;
@MockBean
private CustomerRepository customerRepository;
@Test
void shouldFailFetchingCustomersWhenDatabaseIsDown() {
when(customerRepository.findAll()).thenThrow(new RuntimeException("Cannot connect to database."));
ResponseEntity<String> result = this.testRestTemplate
.exchange("/api/v1/customers", HttpMethod.GET, HttpEntity.EMPTY, String.class);
assertEquals(500, result.getStatusCodeValue());
}
@Test
public void shouldFetchAListOfCustomers(){
ResponseEntity<List<Customer>> result = this.testRestTemplate
.exchange("/api/v1/customers", HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference<>() {});
assertEquals(200, result.getStatusCodeValue());
}
}
运行:
mvn clean install
这有效,并且所有测试 运行。
但它会打开两个容器,如此处的 Docker 图片所示。
如何正确使用单例容器?我只想使用一个。
从容器镜像名称可以看出,容器是不同的。第二个容器是您的数据库 (postgres
),但第一个 (ryuk
) 是辅助容器,默认情况下由 Testcontainer
库本身启动。 Ryuk
在不再需要其他容器 (documentation) 后执行故障安全清理。无需担心,因为它很小 (~5Mb)。
如果你绝对确定你不需要它,你可以在this instruction.
之后禁用ryuk