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

contractTest task cannot use correct profile file when default profile #1981

Closed
tonny1983 opened this issue Sep 25, 2023 · 10 comments
Closed

Comments

@tonny1983
Copy link

Describe the bug
The application use Spring boot 3.1.3 and Spring Contract 4.0.4 with gradle (kotlin DSL).

The application has two application.yml configuration files, the one of which locates in /src/main/resources and the other in /src/test/resources. A BaseTestClass for contract tests is also under the /src/test/java/...
.

The application.yml in main folder configurates a JDBC connection to PostgreSQL DB which is used in production environment and the one in test folder configurates a connetion to in-memory H2 DB which is for testing purpose.

When running the contractTest task, the exception shows

...
Caused by: org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
	at app//org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:342)
	at app//org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:54)
	at app//org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:263)
	at app//org.postgresql.Driver.makeConnection(Driver.java:443)
	at app//org.postgresql.Driver.connect(Driver.java:297)
	at app//com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138)
	at app//com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359)
	at app//com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201)
	at app//com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470)
	at app//com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561)
	at app//com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:100)
	at app//com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112)
	at app//org.flywaydb.core.internal.jdbc.JdbcUtils.openConnection(JdbcUtils.java:48)
	... 179 more
Caused by: java.net.ConnectException: Connection refused
	at java.base/sun.nio.ch.Net.pollConnect(Native Method)
	at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
	at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:549)
	at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597)
	at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
	at java.base/java.net.Socket.connect(Socket.java:633)
	at org.postgresql.core.PGStream.createSocket(PGStream.java:243)
	at org.postgresql.core.PGStream.<init>(PGStream.java:98)
	at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:132)
	at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:258)
	... 191 more

It seems the test using the configurations in the main application.yml file.

I tried to add @ActiveProfiles("test") annotation for BaseTestsClass and then just copy and rename the test application.yml file to test application-test.yml file. Then, the contractTest task works correctly. Therefore, the problem only occurs for default profile, in where the contractTest task loads the main configuration file but the test one.

Sample

The application can be found at repo.

@marcingrzejszczak
Copy link
Contributor

Is this a problem with Contract only? Do you put contract out of the equation does Spring Boot work well with profiles and properties?

@tonny1983
Copy link
Author

Hi @marcingrzejszczak

There are also some JDBC tests in the cc.tonny.catalogservice.adapter.outbound package of the repo, which correctly use the configurations in the application.yml under the test folder. The Spring Boot creates an H2 datasource for those tests as:

[    Test worker] o.s.j.d.e.EmbeddedDatabaseFactory        : Starting embedded database: url='jdbc:h2:mem:1b2816f9-9e79-486d-bad9-26114e817a9b;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false', username='sa'

@marcingrzejszczak
Copy link
Contributor

That's really strange, cause we're not building anything on top of these, we're just using Spring Boot annotations. Any ideas @sbrannen what might be going on here?

@sbrannen
Copy link

sbrannen commented Dec 5, 2023

I admit: it does sound a bit strange. But it doesn't sound to me like it has anything to do with the core Spring Framework (spring-test module).

@ActiveProfiles is from spring-test, but it's only responsible for setting the active profiles in the application context created for the integration test.

It's Spring Boot that is responsible for processing those application*.yml files and honoring the active profiles (or default profile).

Even though they're outdated, the following issues seem somewhat related.

If you cannot sort out the cause, I'd suggest contacting the Spring Boot team.

@marcingrzejszczak
Copy link
Contributor

Thanks! Spring Cloud Contract on the producer side is really just generating the test classes, it's up to the user to setup the base class for the generated test classes. It doesn't impact how you're setting it up so if there are problems with that indeed there can be a problem with Boot. Preferable approach would be to remove Spring Cloud Contract from the equation, create a similar test set up with just Boot (database, a test class, base class that sets up profiles) and see if the problem still persists.

@tonny1983
Copy link
Author

There might be another clue for the problem -- the folders of generated contract tests code.

As in my environment, there are two folders for them -- generated-test-resources and generated-test-sources, the former one of which is empty. Besides, there is also a resources folder which contains the application.yml files for both main and test folders.

截屏2023-12-06 10 08 14

I'm not sure whether it is the reason that the contract tests loads the application.yml file in the main folder because the generated test code is under the contactTest/java folder and it can not load the configuration under resources/test.

@marcingrzejszczak
Copy link
Contributor

Summoning @shanman190 😬 🙏

@shanman190
Copy link
Contributor

So the issue here is the classic classpath order problem.

https://github.com/spring-cloud/spring-cloud-contract/blob/main/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/java/org/springframework/cloud/contract/verifier/plugin/SpringCloudContractVerifierGradlePlugin.java#L195-L199

Since the file name is the same in both main and test the first one that appears on the classpath shadows the other.

I'm pretty positive that it's just a matter of flipping the order in the link above which appears to be the order in which Gradle also uses internally by default.
https://github.com/gradle/gradle/blob/master/platforms/jvm/plugins-java/src/main/java/org/gradle/api/plugins/JavaPlugin.java#L378-L379

@marcingrzejszczak
Copy link
Contributor

Will you file a PR or should I look into that? I think we're releasing SCC today so this would go in in the next release

@shanman190
Copy link
Contributor

@marcingrzejszczak, sure I can grab it. What's the current branch baseline that I should target? 3.1.x?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants