PlaytikaOSS / testcontainers-spring-boot

Container auto-configurations for Spring Boot based integration tests
https://www.playtika.com
MIT License
858 stars 240 forks source link

Subsequent tests with different environment fail with embedded postgres #203

Closed rubengees closed 4 years ago

rubengees commented 4 years ago

I have two test classes, one annotated with:

@SpringBootTest

and the other annotated with:

@AutoConfigureWebTestClient
@SpringBootTest

Individually run, they both work fine. Once I start them together, the one executed later always fails with this error:

Caused by: org.flywaydb.core.internal.exception.FlywaySqlException: 
Unable to obtain connection from database: The connection attempt failed.
------------------------------------------------------------------------------
SQL State  : 08001
Error Code : 0
Message    : The connection attempt failed.

    at org.flywaydb.core.internal.jdbc.JdbcUtils.openConnection(JdbcUtils.java:65)
    at org.flywaydb.core.internal.jdbc.JdbcConnectionFactory.<init>(JdbcConnectionFactory.java:80)
    at org.flywaydb.core.Flyway.execute(Flyway.java:447)
    at org.flywaydb.core.Flyway.migrate(Flyway.java:153)
    at org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer.afterPropertiesSet(FlywayMigrationInitializer.java:65)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792)
    ... 81 more
Caused by: org.postgresql.util.PSQLException: The connection attempt failed.
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:292)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
    at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:195)
    at org.postgresql.Driver.makeConnection(Driver.java:458)
    at org.postgresql.Driver.connect(Driver.java:260)
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:354)
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202)
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:473)
    at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:554)
    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115)
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112)
    at com.zaxxer.hikari.HikariDataSource$$FastClassBySpringCGLIB$$eeb1ae86.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136)
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
    at com.zaxxer.hikari.HikariDataSource$$EnhancerBySpringCGLIB$$d797199.getConnection(<generated>)
    at org.flywaydb.core.internal.jdbc.JdbcUtils.openConnection(JdbcUtils.java:56)
    ... 87 more
Caused by: java.net.SocketException: Connection reset
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
    at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:140)
    at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:109)
    at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:67)
    at org.postgresql.core.PGStream.receiveChar(PGStream.java:335)
    at org.postgresql.core.v3.ConnectionFactoryImpl.enableSSL(ConnectionFactoryImpl.java:411)
    at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:94)
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:192)
    ... 110 more
tdanylchuk commented 4 years ago

Please share your configuration for both tests, how you try to connect to containerized postgres

rubengees commented 4 years ago

I have made these changes after removing h2:

// build.gradle
testImplementation "com.playtika.testcontainers:embedded-postgresql:$embeddedPostgresVersion"
testImplementation "org.springframework.cloud:spring-cloud-starter:$springCloudVersion"
# application.yaml
datasource:  
  url: "jdbc:postgresql://${embedded.postgresql.host}:${embedded.postgresql.port}/${embedded.postgresql.schema}"
  username: ${embedded.postgresql.user}
  password: ${embedded.postgresql.password}
# bootstrap.yaml
embedded:
  postgresql:
    dockerImage: timescale/timescaledb:latest-pg10

I can try to make a minimal sample project later if you like.

tdanylchuk commented 4 years ago

would be awesome, since settings seems to be good for me, just not sure about your image, can u try use default one?

rubengees commented 4 years ago

Okay, will do that later. I can't try without since the application depends heavily on TimescaleDB. That is basically Postgres with an extension and should work (actually does if the tests are executed individually).

rubengees commented 4 years ago

Here is an example project: https://github.com/rubengees/spring-boot-embedded-postgres

You were right, this only happens when using timescaledb! I saw that the GenericContainer is used here instead of the PostgreSQLContainer:

https://github.com/testcontainers/testcontainers-spring-boot/blob/e030533287271f041419c8082396331874e78da4/embedded-postgresql/src/main/java/com/playtika/test/postgresql/EmbeddedPostgreSQLBootstrapConfiguration.java#L63

Later today I tried with the official PostgreSQL container and that worked, probably because of different status checks:

https://github.com/testcontainers/testcontainers-java/blob/f43e799cea8d6ae4aa22927f773b8d0ae5926fc8/modules/postgresql/src/main/java/org/testcontainers/containers/PostgreSQLContainer.java#L33

Would it make sense for this project to depend on the Postgres module?

tdanylchuk commented 4 years ago

ideally yes, we need to reuse vanilla containers, but not sure that we would have time for this in nearest future. Unless there will be more votes on this ticket. Anyways you are free to add PR, be sure that review process will be as short as possible, same as release.

vasilievip commented 4 years ago

@rubengees I guess this issue can be closed?