<#1236 Provider State Parameters Missing in URL Wh...
# pact-js-development
g
#1236 Provider State Parameters Missing in URL When Service is Both Provider and Consumer Issue created by somnath157 When running the mvn test command, the verification test for a provider fails because the URL does not have the path variables loaded from the provider state. This issue occurs when the service acts as both a provider and a consumer for different APIs. Software versions Java : 17 Spring boot: 3.2.1 au.com.dius.pact.consumer.junit5: 4.6.9 au.com.dius.pact.provider.spring6: 4.6.9 Expected behaviour The provider verification test should pass, with the URL including the path variables loaded from the provider state. Actual behaviour The provider verification test fails because the URL does not include the path variables from the provider state. Steps to reproduce 1. Ensure that the BeneficiaryAPIContractVerificationTest and DocumentServiceApiContractTest classes are correctly set up as shown in the provided code. 2. Run mvn test to execute the test cases. 3. Observe that while the consumer test (DocumentServiceApiContractTest) runs successfully, the provider verification test (BeneficiaryAPIContractVerificationTest) fails. Additional Information: This issue occurs specifically when both tests are in the same package. If the tests are in different packages, the issue occurs intermittently depending on the order in which the test classes are executed. Code Samples: `package com.statrys.bankaccount.api.contract; import au.com.dius.pact.consumer.MockServer; import au.com.dius.pact.consumer.dsl.PactDslJsonArray; import au.com.dius.pact.consumer.dsl.PactDslJsonBody; import au.com.dius.pact.consumer.dsl.PactDslWithProvider; import au.com.dius.pact.consumer.junit5.PactConsumerTestExt; import au.com.dius.pact.consumer.junit5.PactTestFor; import au.com.dius.pact.core.model.V4Pact; import au.com.dius.pact.core.model.annotations.Pact; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.statrys.bankaccount.api.client.dto.DocumentInfoDTO; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; import java.util.List; import java.util.Map; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Fail.fail; @ExtendWith(PactConsumerTestExt.class) @PactTestFor(providerName = "document-service") class DocumentServiceApiContractTest { private static final UUID DOCUMENT_CODE = UUID.fromString("fe7edc38-83fd-4ae0-818c-83b5d0b9845f"); private static final UUID DOCUMENT_CODE_NOT_EXISTS = UUID.fromString("b470fdb7-0544-468e-9b7b-c3069f95f45d"); private static final String EMPTY_DOCUMENT_CODE = ""; private static final String DOCUMENT_URL = "https://www.google.com/"; private static final Map<String, String> RES_HEADERS = Map.of("Content-Type", "application/json"); private static final RestTemplate REST_TEMPLATE = new RestTemplate(); private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
Copy code
@BeforeEach
public void setUp() {
    System.setProperty("pact.writer.overwrite", "true");
    System.setProperty("pact.expressions.start", "{");
}

@Pact(consumer = "bank-account-service")
public V4Pact getDocumentList(PactDslWithProvider builder) {
    return builder
            .given("document codes exist")
            .uponReceiving("Request to get document details internally")
            .path("/internal/v1/documents")
            .queryParameterFromProviderState("codes", "codes", DOCUMENT_CODE.toString())
            .method("GET")
            .willRespondWith()
            .status(200)
            .headers(RES_HEADERS)
            .body(new PactDslJsonArray()
                    .object()
                    .uuid("code", DOCUMENT_CODE)
                    .stringType("documentUrl", DOCUMENT_URL)
                    .closeObject()
            )
            .given("document codes not exist")
            .uponReceiving("Request to get document details internally")
            .path("/internal/v1/documents")
            .queryParameterFromProviderState("codes", "codes", DOCUMENT_CODE_NOT_EXISTS.toString())
            .method("GET")
            .willRespondWith()
            .status(200)
            .headers(RES_HEADERS)
            .body(new PactDslJsonArray())
            .given("document codes missing")
            .uponReceiving("Request to get document details internally")
            .path("/internal/v1/documents")
            .queryParameterFromProviderState("codes", "codes", EMPTY_DOCUMENT_CODE.toString())
            .method("GET")
            .willRespondWith()
            .status(422)
            .body(new PactDslJsonBody()
                    .stringType("code")
                    .stringType("message")
                    .stringMatcher("raisedAt", "\\d{13}", "1714983789660")
            )
            .toPact(V4Pact.class);
}

@Test
@PactTestFor(pactMethod = "getDocumentList")
void shouldGetDocumentList(MockServer mockServer) throws JsonProcessingException {
    var baseURL = mockServer.getUrl();
    ResponseEntity<String> responseEntityPresent = REST_TEMPLATE.getForEntity(
            baseURL + "/internal/v1/documents?codes=" + DOCUMENT_CODE,
            String.class);
    assertThat(responseEntityPresent.getStatusCode()).isEqualTo(HttpStatus.OK);
    var body = responseEntityPresent.getBody();
    var documents = OBJECT_MAPPER.readValue(body, new TypeReference<List<DocumentInfoDTO>>() {
    });
    assertThat(documents).hasSize(1);
    assertThat(documents.get(0).getCode()).isEqualTo(DOCUMENT_CODE);
    assertThat(documents.get(0).getDocumentUrl()).isEqualTo(DOCUMENT_URL);
    try {
        REST_TEMPLATE.getForEntity(
                baseURL + "/internal/v1/documents?codes=" + EMPTY_DOCUMENT_CODE,
                String.class);
        fail("should have thrown exception");
    } catch (HttpClientErrorException ex) {
        assertThat(ex.getStatusCode()).isEqualTo(HttpStatus.UNPROCESSABLE_ENTITY);
    }
    ResponseEntity<String> responseEntityEmpty = REST_TEMPLATE.getForEntity(
            baseURL + "/internal/v1/documents?codes=" + DOCUMENT_CODE_NOT_EXISTS,
            String.class);
    assertThat(responseEntityEmpty.getStatusCode()).isEqualTo(HttpStatus.OK);
    var emptyBody = responseEntityEmpty.getBody();
    var documentsList = OBJECT_MAPPER.readValue(emptyBody, new TypeReference<List<DocumentInfoDTO>>() {
    });
    assertThat(documentsList).isEmpty();
}
}` `package com.statrys.bankaccount.api.contract; import au.com.dius.pact.provider.junit5.PactVerificationContext; import au.com.dius.pact.provider.junitsupport.Provider; import au.com.dius.pact.provider.junitsupport.State; import au.com.dius.pact.provider.junitsupport.loader.PactBroker; import au.com.dius.pact.provider.junitsupport.loader.PactBrokerAuth; import au.com.dius.pact.provider.junitsupport.loader.PactBrokerConsumerVersionSelectors; import au.com.dius.pact.provider.junitsupport.loader.SelectorBuilder; import au.com.dius.pact.provider.spring.spring6.PactVerificationSpring6Provider; import au.com.dius.pact.provider.spring.spring6.Spring6MockMvcTestTarget; import com.statrys.bankaccount.api.contract.mocks.BeneficiaryMocks; import com.statrys.bankaccount.api.controller.BeneficiaryApiController; import com.statrys.bankaccount.configuration.ContractConfig; import com.statrys.bankaccount.service.BeneficiaryService; import com.statrys.bankaccount.type.BankServiceMessage; import com.statrys.common.exception.ServiceException; import com.statrys.common.web.handler.CustomResponseEntityExceptionHandler; import com.st… pact-foundation/pact-js