Reputation: 1
The problem is: When i try to use singleton-testcontainer, all my testclasses after first failed by assertions. It means, that even if i see in log that my scenarios was comlete success, Assertions always failed.
The fact is, when i use @Testcontainers and @Container annotation - it's all good.
My first test class.
@SpringBootTest(classes = {ContractSpringBootApplication.class})
@ExtendWith({MockitoExtension.class, OutputCaptureExtension.class})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@ActiveProfiles("test")
public class UpdateMergeTest extends AbstractTestcontainersTest {
@SpyBean
@Autowired
private TechMergeUpdateRepo techMergeUpdateRepo;
@BeforeEach
void clean() {
techMergeUpdateRepo.deleteAll();
}
My second test class. (does the same things, but used more repositories)
@SpringBootTest(classes = {ContractSpringBootApplication.class})
@ExtendWith({MockitoExtension.class, OutputCaptureExtension.class})
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@ActiveProfiles("test")
public class UpdateEntityTest extends AbstractTestcontainersTest {
@SpyBean
@Autowired
private TechMergeUpdateRepo techMergeUpdateRepo;
@SpyBean
@Autowired
private UpdateEntityRepo updateEntityRepo;
@BeforeEach
void clean() {
techMergeUpdateRepo.deleteAll();
updateEntityRepo.deleteAll();
}
My "singleton" testcontainer class.
public abstract class AbstractTestcontainersTest {
private final static String DATABASE_NAME = "test_name";
public static final PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>("postgres:12")
.withReuse(true)
.withDatabaseName(DATABASE_NAME);
static {
postgresContainer.start();
}
@DynamicPropertySource
public static void overrideProps(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgresContainer::getJdbcUrl);
registry.add("spring.datasource.username", postgresContainer::getUsername);
registry.add("spring.datasource.password", postgresContainer::getPassword);
registry.add("spring.datasource.driver-class-name", postgresContainer::getDriverClassName);
}
}
After tests i always get this: enter image description here
BUT!
If I change my AbstractTestcontainersTest for:
@Slf4j
@Testcontainers
public abstract class AbstractTestcontainersTest {
private final static String DATABASE_NAME = "test_name";
@Container
public static final PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>("postgres:12")
.withReuse(true)
.withDatabaseName(DATABASE_NAME);
static {
postgresContainer.start();
}
@DynamicPropertySource
public static void overrideProps(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgresContainer::getJdbcUrl);
registry.add("spring.datasource.username", postgresContainer::getUsername);
registry.add("spring.datasource.password", postgresContainer::getPassword);
registry.add("spring.datasource.driver-class-name", postgresContainer::getDriverClassName);
}
}
It will start working correctly.
I checked the log output. The feeling is that the problem is somewhere in the “underrun” of Spring tests, in test classes, starting from the second. I checked the logs - my “scenarion” is fully completed and works correctly, but the assertions are falling
I checked the log output. The feeling is that the problem is somewhere in the “underrun” of Spring tests, in test classes, starting from the second.
Upvotes: 0
Views: 824
Reputation: 354
I guess you are trying to reuse the same containers for all the tests that extends your abstract integration test. You can fin documentation about the singleton pattern here.
I seems you are mixing both automatic and manual lifecycle management.
@TestContainer
and @Container
annotations, will create, start, and stop the container according to the test classes and spring context, but you would potentially have one container per class (that extends Abstract Integration Test). Maybe singleton pattern
is working because you have configured the reuse
flag.
You can manage the lifecycle of the container using the static block to start the container, as you did, but AFAIK it isn't compatible with @TestContainer
and @Container
annotation.
So, you can try the following:
@Slf4j
public abstract class AbstractTestcontainersTest {
private final static String DATABASE_NAME = "test_name";
public static final PostgreSQLContainer<?> postgresContainer = new PostgreSQLContainer<>("postgres:12")
.withDatabaseName(DATABASE_NAME);
static {
postgresContainer.start();
}
@DynamicPropertySource
public static void overrideProps(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgresContainer::getJdbcUrl);
registry.add("spring.datasource.username", postgresContainer::getUsername);
registry.add("spring.datasource.password", postgresContainer::getPassword);
registry.add("spring.datasource.driver-class-name", postgresContainer::getDriverClassName);
}
}
Please, note the @DynamicPropertySource
can be drop if you are using SpringBoot 3.X, see here
Upvotes: 0
Reputation: 1
The problem was using @SpyBean annotations.
Because the context was not re-raised completely, in the case of a singleton test container. When asserting, all @SpyBeans after the first class pointed to Proxy without explicit proxying.
Moving the @SpyBean annotated injections to the base class (AbstractTestcontainersTest) solved the problem.
Upvotes: 0