During my unit tests using Spock and Testcontainers, the JpaRepository is not functioning properly and is not being wired correctly. This issue persists even in non-integration tests.
As suggested in another discussion, I attempted to resolve the issue by adding the spock-spring dependency to my pom.xml file. It didn't work.
No matter the scenario, the repository consistently returns as null in all instances.
An example:
@Testcontainers
class PostgresTestContainer extends Specification {
@Autowired
private PersonRepository personRepository
@Shared
PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer("postgres:12-alpine")
.withDatabaseName("test")
.withUsername("test")
.withPassword("test")
def "waits until postgres accepts jdbc connections"() {
when: "querying the database"
def response = personRepository.findAll()
then: "result is returned"
response == 0
}
}
The database is being initialized using PostgresContainer
and Testcontainers
annotation. However your test infrastructure doesn't know about the database. If using spring boot, then few things are missed
SpringBootTest
or DataJpaTest
annotation on top of the class. This way the spring application context is created with the right classes and PersonRepository
will be injectedstatic postgresContainer = new PostgreSQLContainer("postgres:12-alpine")
@Shared
PostgreSQLContainer <?> cassandra = cassandraContainer
@DynamicPropertySource
static void registerProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgresContainer::getJdbcUrl);
registry.add("spring.datasource.username", postgresContainer::getUsername);
registry.add("spring.datasource.password", postgresContainer::getPassword);
}
I would suggest to separate the container setup like the following:
PostgresEnvrionement
@Testcontainers
public class PostgresEnvironment {
@Container
public static PostgreSQLContainer postgreSQLContainer = PostgresTestContainer.getInstance();
}
PostgresTestContainer
public class PostgresTestContainer extends PostgreSQLContainer<PostgresTestContainer> {
public static final String IMAGE_VERSION = "postgres:13.5";
public static final String DATABASE_NAME = "test";
private static PostgresTestContainer container;
private PostgresTestContainer() {
super(IMAGE_VERSION);
}
public static PostgresTestContainer getInstance() {
if (container == null) {
container = new PostgresTestContainer().withDatabaseName(DATABASE_NAME);
}
return container;
}
@Override
public void start() {
super.start();
System.setProperty("DB_URL", container.getJdbcUrl());
System.setProperty("DB_USERNAME", container.getUsername());
System.setProperty("DB_PASSWORD", container.getPassword());
}
@Override
public void stop() {
}
}
In your test file extend the PostgresEnvironment
@ActiveProfiles("test")
@SpringBootTest(classes = MainSpringBootApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AssembleEventRepositoryIntegrationTest extends PostgresEnvrionement{
// autowire jpa
// write tests
}
in your application-test.yml
file in the resources section under the test directory
spring:
datasource:
password: ${DB_USERNAME}
username: ${DB_PASSWORD}
driver-class-name: org.postgresql.Driver
url: ${DB_URL}
Also make sure that your main application.yml
file that is being used once launching your application (not in for running your tests) matches the same syntax as your test profile.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.