Pact-jvm: @PactBroker not reading Spring properties with JUnit 5

Created on 21 Feb 2020  路  13Comments  路  Source: pact-foundation/pact-jvm

If you provide system properties in Spring application.yml these won't be read by the @PactBroker annotation when running with JUnit 5. This works fine if you provide them as normal system properties.

This issue seems to have been fixed for the JUnit 4 runners in here: https://github.com/DiUS/pact-jvm/issues/632

I can see that the problem has been fixed by adding a property resolver, and that it is also possible to pass a valueResolver attribute for the @PactBroker annotation. However, since you need a Spring context to be able to create such a resolver for Spring, it cannot be done with the annotation.

I also tried to add a resolver into PactVerificationContext in @BeforeEach but that didn't seem to do the trick.

enhancement

Most helpful comment

I've created a new module pact-jvm-provider-junit5-spring with a TestTemplateInvocationContextProvider that extends the current JUnit 5 one (PactVerificationSpringProvider). This should allow you to configure all the properties in the Spring context.

All 13 comments

I am also having the same issue.
The preferred approach to ask questions on stackflow did not help either.
https://stackoverflow.com/questions/60153108/provider-test-integration-with-pact-broker-for-spring-boot-junit5-configuratio

Waiting for the answer

I've created a new module pact-jvm-provider-junit5-spring with a TestTemplateInvocationContextProvider that extends the current JUnit 5 one (PactVerificationSpringProvider). This should allow you to configure all the properties in the Spring context.

That鈥檚 awesome! Thank you for such a quick response to the issue. This will make the developer experience smoother when running tests out of the box, with the broker having a default configuration in the properties file.

HI @uglyog , I noticed a small inconsistency in the implementation of the SpringEnvironmentResolver.kt

The propertyDefined() method relies only on environment, while the resolveValue() uses SystemPropertyResolver also as backup.
Also, the Spring _environment_ property resolution considers the system properties also when resolving a value. That has a higher preference. Any specific reason why?

@vtapadia I've removed the SystemPropertyResolver fallback

@vtapadia removing the fallback breaks the pact loader, so I'm reverting the change

Tested this with version 4.0.7 and replaced the PactVerificationInvocationContextProvider with the PactVerificationSpringProvider. Also added the missing properties to application.yml.

However, I'm still getting this:

java.lang.IllegalArgumentException: Invalid pact broker host specified ('${pactbroker.host:}'). Please provide a valid host or specify the system property 'pactbroker.host'.

    at au.com.dius.pact.provider.junit.loader.PactBrokerLoader.getPactBrokerSource(PactBrokerLoader.kt:176)
    at au.com.dius.pact.provider.junit.loader.PactBrokerLoader.description(PactBrokerLoader.kt:62)
    at au.com.dius.pact.provider.junit5.PactVerificationInvocationContextProvider.resolvePactSources(PactJUnit5VerificationProvider.kt:395)
    at au.com.dius.pact.provider.junit5.PactVerificationInvocationContextProvider.provideTestTemplateInvocationContexts(PactJUnit5VerificationProvider.kt:366)

The stack trace suggests that it's still using the PactVerificationInvocationContextProvider and not the Spring specific one.

Am I missing something here?

I did some debugging with this, and it seems that while the original commit to implement this worked, the change on line 395 of PactJUnit5VerificationProvider.kt on commit https://github.com/DiUS/pact-jvm/commit/2f1070bc72bf3b70372a77191c3525c6327aae47 has broken the functionality.

It seems that calling it.description() tries to use the resolver, but it has not yet been correctly set.

In PactBrokerLoader.kt:

  override fun description(): String {
    val resolver = setupValueResolver()
    // ...
  }

  private fun setupValueResolver(): ValueResolver {
    var valueResolver: ValueResolver = SystemPropertyResolver()
    // ...
    return valueResolver
  }

4.0.8 released with this change

I'm using this dependency

    <!-- https://mvnrepository.com/artifact/au.com.dius/pact-jvm-provider-junit5 -->
    <dependency>
        <groupId>au.com.dius</groupId>
        <artifactId>pact-jvm-provider-junit5</artifactId>
        <version>4.0.10</version>
    </dependency>

My code:

@PactBroker(scheme = "https", host = "${pactbroker.host}", authentication = @PactBrokerAuth(token = "${pactbroker.auth.token}"))
@Provider("PriceService")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@ExtendWith(SpringExtension.class)

public class PriceServicePactTests {

@LocalServerPort
private final int port = 8082;
ObjectMapper objectMapper = new ObjectMapper();
@MockBean
private PriceDAO priceDao;

@BeforeEach
public void setupTest(final PactVerificationContext context) {
    System.setProperty("pact.provider.tag", "dev");
    System.setProperty("pact.provider.version", "1.0.0");
            context.setTarget(new HttpTestTarget("localhost", port, "/"));
}

@BeforeClass
public void enablePublishingPact() {
    System.setProperty("pact.verifier.publishResults", "true");
}

@TestTemplate
@ExtendWith(PactVerificationInvocationContextProvider.class)
void pactVerificationTestTemplate(final PactVerificationContext context) {
    context.verifyInteraction();
}

and facing the same problem: java.lang.RuntimeException: Could not resolve property "pactbroker.host" in the system properties or environment variables and no default value is supplied

any help would be appreciated.

Thanks in advance.

@gustavotpd pactbroker.host needs to be defined as a JVM system property somewhere. See https://maven.apache.org/surefire/maven-surefire-plugin/examples/system-properties.html on how to do this with the Maven Surfire plugin, which is what runs the tests with Maven.

Hi, I want to disable pact tests in local build . With regards to same I am using @IgnoreNoPactsToVerify (ignoreIoErrors = "${pact.verification.ignoreIoErrors}") and I am setting the property in system arg as mvn -s H:\settings.xml -DargLine="-Dpact.verification.ignoreIoErrors=true however I still get the error -

Could not resolve property "${pact.verification.ignoreIoErrors}" in the system properties or environment variables and no default
value is supplied

I am using pact plugin
<plugin> <groupId>au.com.dius</groupId> <artifactId>pact-jvm-provider-maven_2.12</artifactId> <version>${pact.jvmprovider}</version>

Can you pls help?

@vijays2017 the property needs to be set on the test JVM. See https://maven.apache.org/surefire/maven-surefire-plugin/examples/system-properties.html on how to do this with the Maven Surfire plugin, which is what runs the tests with Maven.

Was this page helpful?
0 / 5 - 0 ratings