Pact provider tests broken: pactVerificationTestTemplate » PreconditionViolation

5.9k views Asked by At

I'm quite new to CDC testing and only make my first steps. I've deployed the Pact-Broker (docker-compose), running at localhost:80. The consumer sends the generated pacts successfully to the broker, but it seems that the provider can't get a valid contract (but this is only the assumption).

I'm using spring-boot, maven, jUnit5. Application tests are running on Ubuntu. Using PactFolder with the consumer-generated pact-contract in local directory results in successful tests.

When I'm switching to @PactBroker annotation, the provider is able to connect to the broker and it receives the following response (I got it from debug logs):

{"_links":
    {"self":{
        "href":"http://localhost/pacts/provider/provider-    name/latest","title":"Latest pact versions for the provider provider-name"},
    "pb:provider":{"href":"http://localhost/pacticipants/provider-name",
        "name":"provider-name"},
    "pb:pacts":[
        {"href":"http://localhost/pacts/provider/provider-name/consumer/consumer-name/version/1.0.0",
        "title":"Pact between consumer-name (v1.0.0) and provider-name",
        "name":"consumer-name"} 
     ],
    "provider":{
        "href":"http://localhost/pacticipants/provider-name",
        "title":"provider-name",
        "name":"DEPRECATED - please use the pb:provider relation"
     },
    "pacts":[
            {"href":"http://localhost/pacts/provider/provider-name/consumer/consumer-name/version/1.0.0",
            "title":"DEPRECATED - please use the pb:pacts relation. Pact between consumer-name (v1.0.0) and provider-name",
            "name":"consumer-name"
            }
        ]
    }
}

And the test run results in the following:

[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 9.758 s 
FAILURE! - in com.tis.payment.mapper.PaymentMapperApplicationTests
[ERROR] pactVerificationTestTemplate{PactVerificationContext}  
Time elapsed: 9.752 s  
ERROR!
org.junit.platform.commons.util.PreconditionViolationException: 
No supporting TestTemplateInvocationContextProvider provided an invocation context
[INFO] 
[INFO] Results:
[INFO] 
[ERROR] Errors: 
[ERROR]   PaymentMapperApplicationTests.pactVerificationTestTemplate » PreconditionViolation
[INFO] 
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0

As using the local pact file makes tests green, I suppose that the reason is not in the code of my test class, though if it could be helpful, I provide it here:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
        properties = "server.port=8082")
@Provider("provider-name")
@PactBroker(host = "localhost", port = "80", tags="latest")
//@PactFolder("target/pacts") # uncomment to use local pact files
public class ApplicationTests {

    @MockBean
    private ProviderServiceClient providerServiceClient;

    @BeforeEach
    void setupTestTarget(PactVerificationContext context) {
        context.setTarget(new HttpTestTarget("localhost", 8082, "/"));
    }

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

    @State({"valid payment file"})
    public void toValid() {
        ServiceResponse response = new ServiceResponse();
        response.setBatchId("test");
        response.setId(1L);
        when(providerServiceClient.save(any())).thenReturn(response);
    }

    @State({"invalid payment file"})
    public void toInvalid() {
    }
}

As using local pact files is not an option, I really wonder how to fix the error and will be grateful for any helpful comments.

maven pact dependencies:

<dependency>
    <groupId>au.com.dius</groupId>
    <artifactId>pact-jvm-model</artifactId>
    <version>3.5.22</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>au.com.dius</groupId>
    <artifactId>pact-jvm-provider-junit5_2.12</artifactId>
    <version>3.5.22</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>au.com.dius</groupId>
    <artifactId>pact-jvm-consumer-junit5_2.12</artifactId>
    <version>3.5.22</version>
    <scope>test</scope>
</dependency>

Plugin for maven to publish the consumer's pacts:

<plugin>
    <groupId>au.com.dius</groupId>
    <artifactId>pact-jvm-provider-maven_2.12</artifactId>
    <version>3.5.22</version>
    <configuration>
        <pactBrokerUrl>http://localhost:80</pactBrokerUrl>
        <trimSnapshot>true</trimSnapshot>
        <!-- Defaults to false -->
    </configuration>
</plugin>

the pact-provider docker-compose.yml:

version: '2'
    services:
        postgres:
          image: postgres
          restart: always
          # healthcheck:
            # test: psql postgres --command "select 1" -U postgres
          ports:
            - "5432:5432"
          environment:
            POSTGRES_USER: postgres
            POSTGRES_PASSWORD: password
            POSTGRES_DB: postgres
        broker_app:
          image: dius/pact-broker
          depends_on: 
            - postgres
          ports:
            - "80:80"
          links:
            - postgres
          environment:
            PACT_BROKER_DATABASE_USERNAME: postgres
            PACT_BROKER_DATABASE_PASSWORD: password
            PACT_BROKER_DATABASE_HOST: postgres
            PACT_BROKER_DATABASE_NAME: postgres
2

There are 2 answers

0
Ronald Holshausen On

The JUnit 5 error org.junit.platform.commons.util.PreconditionViolationException: No supporting TestTemplateInvocationContextProvider provided an invocation context means no test context was provided, so the templated test method could not be invoked. This is probably due to there not being any pacts to verify (each pact results in an invocation context).

Now to addressing the actual issue as to why you are not getting any pacts to verify from the broker. The Pact Broker is essentially a repository, and the JUnit 5 verification framework will use all the annotations on the pact class to create a query to send to the Pact Broker. This query is not returning any pacts, so there must be a mismatch somewhere.

The only thing I can see from the information you have provided is the URL "http://localhost/pacts/provider/provider- name/latest" in the JSON has an issue (there is whitespace in the provider name). If that is not just a formatting issue with SO, then that won't match (the broker will probably return a 404 with that URL).

If that is not the issue, then check that when you run the verification from Maven, you can access the broker in the same way that the test framework is. Enabling DEBUG level logging will show you all the requests being made. Use something like curl and try the same requests to see what you get.

0
Hermina Grayson On

I want to add information for newbies like me. I have encountered the following exception in my Spring Boot Camel project:

org.junit.platform.commons.PreconditionViolationException: You must register at least one TestTemplateInvocationContextProvider that supports @TestTemplate method

and this is the page where googling took me, so I'll post how fixed that issue and it is really simple. When exporting @Test annotation, add it from org.junit.jupiter.api, not from org.apache.camel.test.junit5.params.