How to inject dynamic id for Pact test from provider to consumer using REST Assured

1.9k views Asked by At

I need to check an api of the type /meeting/id using Pact tests and REST Assured. The id may change and I'd like to create an item before the test and inject their id to overwrite what is set as part of the url path for the contract but not sure how to go about that please?

Here my consumer:

@ExtendWith(PactConsumerTestExt.class)
public class PactConsumerTest {

Map<String, String> headers = new HashMap<>();


String storeMeetingPath = "/meeting/256";

@Pact(provider = VC, consumer = ED_UI)
public RequestResponsePact createPact(PactDslWithProvider builder) {

    headers.put("Content-Type", "application/json");
    headers.put("Accept", "application/json");

    return builder
            .given("A request to retrieve a meeting for a user")
            .uponReceiving("A request to retrieve a meeting for a user")
            .path(storeMeetingPath)
            .method("GET")
            .headers(headers)
            .willRespondWith()
            .body(new PactDslJsonBody()
                    .integerType("meetingId", 3)
                    .stringType("meetingTitle", "My title")
                    .stringType("meetingDescription", "My description"))
            .status(200)
            .toPact();
}


@Test
@PactTestFor(providerName = VC, port = "8080")
public void runTest() {

    //Mock url
    RestAssured.baseURI = "http://localhost:8080";
    RequestSpecification rq = RestAssured
            .given()
            .headers(headers)
            .when();

    rq.get(storeMeetingPath);

}

}

And here my provider:

@Provider(VC)
@PactFolder("target/pacts")
public class PactProviderTest {

@TestTemplate
@ExtendWith(PactVerificationInvocationContextProvider.class)
void pactTestTemplate(PactVerificationContext context, HttpRequest request) {
    request.addHeader("Authorization", AUTHORIZATION_TOKEN);
    context.verifyInteraction();
}

@BeforeEach
void before(PactVerificationContext context) {
    context.setTarget(new HttpsTestTarget(getBasePactEndpoint(), 443, "/"));

    // Will create a meeting and retrieve the id from here but how to use this to overwrite what is there on the consumer?       

    getAuthorizationToken(UserType.TEACHER);
}

@State("A request to retrieve a meeting for a user")
public void sampleState() {

}

}

Thank you very much.

1

There are 1 answers

7
Francislainy Campos On BEST ANSWER

I've learned the answer for this and here it is in case it may be helpful to anyone else:

Replace this line on the consumer contract

.path(storeMeetingPath)

With

.pathFromProviderState("/meeting/${id}", "/meeting/500") // 500 is just a sample for the data type to be inferred. It can be any value from that same type.

So that we'd have a template with a default value.

And change this on provider side

@State("A request to retrieve a meeting for a user")
public void sampleState() {

} 

To have this instead, so that it returns a map which would set the key and value for the element to be injected.

@State("A request to retrieve a meeting for a user")
public Map sampleState() {

    Map<String, Integer> map = new HashMap<>();
    map.put("id", 391); // id for the meeting I want to retrieve.

    return map;
}

Auxiliar documentation:

Consumer: https://github.com/DiUS/pact-jvm/tree/master/consumer#having-values-injected-from-provider-state-callbacks

Provider: https://github.com/DiUS/pact-jvm/tree/master/provider/junit#returning-values-that-can-be-injected