Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When using JPA and ImportTestcontainers, test context may fail to refresh due to "Mapped port can only be obtained after the container is started" #40585

Closed
ivangfr opened this issue Apr 30, 2024 · 2 comments
Assignees
Labels
type: regression A regression from a previous release
Milestone

Comments

@ivangfr
Copy link

ivangfr commented Apr 30, 2024

Hi, I've upgraded this project from Spring Boot 3.1.4 to 3.2.5.

After that, I've started having issues in my test cases.

I am defining the MyContainers interface

public interface MyContainers {

    @Container
    @ServiceConnection
    PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>("postgres:16.1");
}

Then, using the ImportTestcontainers annotation

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ImportTestcontainers(MyContainers.class)
class TeamDetailControllerTest implements MyContainers {
   ...
}

It seems that the test cases are not waiting for the containers to start

2024-04-30T15:20:41.230+02:00 ERROR 72102 --- [spring-data-jpa-relationships] [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataSourceScriptDatabaseInitializer' defined in class path resource 
[org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Unsatisfied dependency expressed through method 'dataSourceScriptDatabaseInitializer' parameter 0: Error creating bean with name 'dataSource' defined in class path resource 
[org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Failed to instantiate 
[com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception with message: Mapped port can only be obtained after the container is started

If I downgrade to Spring Boot 3.1.4, the test cases will run ok.

How to reproduce

  1. Clone: git clone https://github.com/ivangfr/spring-data-jpa-relationships.git
  2. Run: ./mvnw clean test

Thanks

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 30, 2024
@scottfrederick scottfrederick added type: regression A regression from a previous release and removed status: waiting-for-triage An issue we've not yet triaged labels Apr 30, 2024
@scottfrederick scottfrederick added this to the 3.2.x milestone Apr 30, 2024
@wilkinsona wilkinsona self-assigned this May 21, 2024
@wilkinsona
Copy link
Member

Here's a minimal reproducer:

import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;

import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.weaving.LoadTimeWeaverAware;
import org.springframework.instrument.classloading.LoadTimeWeaver;

@SpringBootTest
@ImportTestcontainers(MyContainers.class)
public class LoaderTimeWeaverAwareConsumerImportTestcontainersTests implements MyContainers {

	@Test
	void test() {

	}

	@Configuration
	@ImportAutoConfiguration(DataSourceAutoConfiguration.class)
	static class TestConfiguration {

		@Bean
		LoaderTimeWeaverAwareConsumer loadTimeWeaverAwareConsumer(JdbcConnectionDetails connectionDetails) {
			return new LoaderTimeWeaverAwareConsumer(connectionDetails);
		}

	}

	static class LoaderTimeWeaverAwareConsumer implements LoadTimeWeaverAware {

		public LoaderTimeWeaverAwareConsumer(JdbcConnectionDetails jdbcConnectionDetails) {
			jdbcConnectionDetails.getJdbcUrl();
		}

		@Override
		public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) {
		}

	}

}

interface MyContainers {

	@Container
	@ServiceConnection
	PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>("postgres:16.1");

}

The problem in the real app is that the entity manager factory implements LoadTimeWeaverAware. This ultimately results in an early call to jdbcConnectionDetails.getJdbcUrl() being made before the container has been started. The involvement of LoadTimeWeaverAware means that it happens before the configuration has been frozen so post-processing hasn't triggered general container initialization. The container bean itself also hasn't been post-processed yet so it's not been started.

@philwebb
Copy link
Member

This looks similar to #38913

@wilkinsona wilkinsona modified the milestones: 3.2.x, 3.2.6 May 22, 2024
@wilkinsona wilkinsona changed the title Mapped port can only be obtained after the container is started When using JPA and ImportTestcontainers, test context may fail to refresh due to "Mapped port can only be obtained after the container is started" May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

5 participants