How to Verify Pacts Against an API That Requires an Auth Token

Add Authorization header to provider request

The header is a part of the contract, I'd propose to propagate it from the consumer side as it does affect the response. A client might want to send you an auth header that causes 403 - it's a contract as well.

Best practices are:

  • Keep the header constant from run-to-run
    • all the values in JWT must be constants, e.g. you can set a constant date inside
  • But JWT token expiry time to something long (aka 2122 till year) to prevent expiration failure on the provider side

The consumer pact will look like:

...
.uponReceiving("A parameterized entities query")
.path("/api/2.0/entities")
.matchHeader("Authorization", "Bearer .*", "Bearer xxxxxxxxxx")
...
.method("GET")
.willRespondWith()
.headers(headers)
.status(200)
.body(body)
.toPact();
  • .matchHeader("Authorization", "Bearer .*", "Bearer xxxxxxxxxx")
    • Bearer xxx goes as an example and the exact value on provider side to call it
    • Bearer .* will be used on the consumer side to verify the request header when you call pact stub server

PACT-JS - Provider contract verification error/failure - PactFlow

It's quite simple. You have defined the provider in you consumer test (and what's in the contract) as pact-provider.

In your provider test, however, it is called Clients Service.

When your provider test is trying to discover the contracts, it uses the provider name as the key. Because there is no provider called Clients Service it's getting a a 404.

Either

  1. Update the provider name in the consumer to to Clients Service (and delete the old integration)
  2. Update the provider name to pact-provider

(1. seems like the right thing to do)

Pact verification failed! with console error Missing requests: GET /users/login

Pact expects you to actually make the call to the endpoint you're mocking in Pact.

Missing requests: GET /users/login

This error says "you said you'd make a GET call to /users/login but I didn't receive it".

jest.mock("axios");

This looks like you're mocking the HTTP client Axios. Now you have a mock for the thing that needs to send requests to the Pact Mock.

In a Pact test, think of it as a unit tests for your API client code. The actual request needs to be sent to the Pact Mock and Pact will check the correct request was made, and return back the mocked response.

So the solution is simple:

  1. Remove all of the axios mocking
  2. Provide a way to modify the API target for loginUser
  3. Configure your API client to send the request to localhost:1234 instead of the real thing before running the tests

(NOTE: you can have pact find a free port dynamically by not setting the port option, and take the host from the response from the setup() call)

Pact: Solving PactMismatchesException

Pact doesn't intercept your requests, so this call doesn't actually talk to the Pact mock server, hence why it was not received - it's going to the real API:

        HttpUriRequest request = new HttpGet("https://api.ipify.org");

You don't test against real API in Pact in the consumer test, you mock out the provider and test using the Pact Mock. It will then generate a contract that the provider can then use to verify your expectations:

It should be:

    @Test
@PactTestFor(pactMethod = "apiIsReachablePact")
public void apiIsReachable(MockServer mockServer) throws IOException {

//Given
HttpUriRequest request = new HttpGet(mockServer.getUrl());

//When
HttpResponse httpResponse = HttpClientBuilder.create().build().execute(request);

//Then
assertEquals(httpResponse.getStatusLine().getStatusCode(), HttpStatus.SC_OK);
}

See this example and this workshop for more.

Unauthorised error when publishing java contract to pact flow using jenkins

It's working now.
As the publishing step comes from the maven pact jvm plugin we needed to add a way for it to get the token by adding this line to the plugin.

<pactBrokerUrl>https://hmhco.pact.dius.com.au/</pactBrokerUrl>

So now we have

<plugin>
<groupId>au.com.dius</groupId>
<artifactId>pact-jvm-provider-maven</artifactId>
<version>${pact.plugin.version}</version>
<configuration>
<pactDirectory>target/pacts</pactDirectory>
<pactBrokerUrl>https://hmhco.pact.dius.com.au/</pactBrokerUrl>
<!--suppress UnresolvedMavenProperty -->
<pactBrokerToken>${pactbroker.auth.token}</pactBrokerToken>
<projectVersion>${project.version}</projectVersion>
<trimSnapshot>true</trimSnapshot>
</configuration>
</plugin>


Related Topics



Leave a reply



Submit