I have a service built with spring boot using gradle (gradle file at the bottom if needed) and Junit5. Many of the questions on stackoverflow are for maven and Junit4 and I have trouble translating the answers. My pact producer test runs and tests correctly against the contract on the broker. However the result of the successful verification is not sent to the broker. What do I have to do for that to happen?
The pact comes from 'other Service' and verifies that 'my service' correctly returns three cute cats. This is what the test looks like:
package com.miau.package;
// imports
@Provider("my_service")
@Consumer("other_service")
@PactBroker(authentication = @PactBrokerAuth(username = "pact",
password = "${pactPassword}"), //NOSONAR hardcoded password hint no password, just variable
host = "pact-broker.apps.home.io/", port = "443",
tags = "sandbox"
)
@SpringBootTest(classes = Application.class,
properties = { "spring.profiles.active=pact,fake-oauth2", "pact.verifier.publishResults=true" },
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Tag("pact")
@ExtendWith({SpringExtension.class})
public class OtherServiceContractVerifier {
@LocalServerPort
int port;
@Autowired
Application application;
@BeforeEach
void before(PactVerificationContext context) {
HttpTestTarget target = new HttpTestTarget("localhost", port, "/my_service");
context.setTarget(target);
}
@TestTemplate
@ExtendWith(PactVerificationInvocationContextProvider.class)
void executePact(PactVerificationContext context) {
context.verifyInteraction();
}
@State("3 cute cats exist")
public void stateThreecuteCatsExists() {
// make 3 cute cats exist in database
}
}
When running ./gradlew pactTest pactPublish
everything works fine. The test passes and if I change the state to only have 2 cats, the test will fail because the pact requires the service to return 3 cats. However the pact broker does not show the successful verification. What do I need to do for that?
I have tried, but seems to be wrong:
Run ./gradlew pactVerify
-> "No service providers are configured".
Not sure what he needs service providers for, as the test gives all the necessary information. But after some googeling I turned up with this and added it to my build.gradle:
Pact {
broker {
pactBrokerUrl = "https://pact-broker.apps.home.io/"
pactBrokerUsername = "pact"
pactBrokerPassword = pactPassword
}
serviceProviders {
'my_service' {
fromPactBroker {
selectors = latestTags('Sandbox')
}
}
}
}
Not sure why he would need that information, it all already exists in the Pact test. but at least it changes the output of ./gradlew pactVerify
, now it lists the contract and attempts to verify it only to fail with Connect to localhost:8080 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused (Connection refused)
This seems to be the wrong approach as it doesn't use the existing Test at all. I haven't found how to tell it, to use the existing OtherServiceContractVerifier
test.
Pact related content of gradle file (I incorperated the answer from this question to no avail):
{
buildscript {
if (!project.hasProperty('pactPassword')) {
pactPassword = ''
}
if (!project.hasProperty('pactTags')) {
pactTags = ''
}
}
}
plugins {
id "au.com.dius.pact" version "4.1.7"
}
apply plugin: 'au.com.dius.pact'
task pactTest(type: Test) {
environment "pactPassword", "$pactPassword"
description = 'Runs pact tests.'
group = 'verification'
useJUnitPlatform()
outputs.upToDateWhen { false }
testClassesDirs = sourceSets.pactTest.output.classesDirs
classpath = sourceSets.pactTest.runtimeClasspath
shouldRunAfter test
}
check.dependsOn pactTest
dependencies {
pactTestImplementation "au.com.dius:pact-jvm-consumer-junit5:4.0.10"
pactTestImplementation "au.com.dius:pact-jvm-consumer-java8:4.0.10"
pactTestImplementation "au.com.dius:pact-jvm-provider-junit5:4.0.10"
pactTestImplementation "au.com.dius:pact-jvm-provider:4.0.10"
}
test {
useJUnitPlatform {
excludeTags "pact"
}
}
pact {
publish {
pactBrokerUrl = "https://pact-broker.apps.home.io/"
pactBrokerUsername = "pact"
pactBrokerPassword = pactPassword
tags = pactTags.tokenize(',')
}
}
You seem to be mixing the Gradle verification process (./gradlew pactVerify
) with JUnit one (e.g. OtherServiceContractVerifier
).
Both can be configured via
For gradle, see https://docs.pact.io/implementation_guides/jvm/provider/gradle/#project-properties.
For JUnit see https://docs.pact.io/implementation_guides/jvm/provider/junit/#publishing-verification-results-to-a-pact-broker
So setting the following will enable that (note: you should only publish from CI)
System.setProperty("pact.verifier.publishResults", "true");
Example project that uses JUnit: https://github.com/pactflow/example-provider-springboot