Search code examples
pactpact-jvm

PactRunner ignores @DefaultRequestValues


I'm trying to test my first Pact file, and I'm stuck on setting headers for the request made to the producer.

I'm trying to get a 404 when a request is made to a user API with an invalid userId, as defined in the following Pact file:

{
  "consumer": {
    "name": "ios-client"
  },
  "provider": {
    "name": "user-service"
  },
  "interactions": [
    {
      "description" : "Request for a User Id that does not exist should return 404",
      "provider_state": "User with id NOPE does not exist",
      "request": {
        "method": "GET",
        "path" : "/users/NOPE"
      },
      "response": {
        "status": 404,
        "body" : ""
      }
    }
  ]
}

The failing test is as follows:

import au.com.dius.pact.consumer.DefaultRequestValues;
import au.com.dius.pact.consumer.dsl.PactDslRequestWithPath;
import au.com.dius.pact.consumer.dsl.PactDslRequestWithoutPath;
import au.com.dius.pact.provider.junit.PactRunner;
import au.com.dius.pact.provider.junit.Provider;
import au.com.dius.pact.provider.junit.State;
import au.com.dius.pact.provider.junit.loader.PactBroker;
import au.com.dius.pact.provider.junit.target.HttpTarget;
import au.com.dius.pact.provider.junit.target.Target;
import au.com.dius.pact.provider.junit.target.TestTarget;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.springframework.boot.SpringApplication;
import org.springframework.http.HttpHeaders;
import .....UserServiceApplication;
import .....UserControllerIT;

import java.util.HashMap;
import java.util.Map;

@RunWith(PactRunner.class)
@Provider("user-service")
@PactBroker(host="${pactbroker.hostname:localhost}", port = "80")
public class PactTest {

    @TestTarget
    public final Target target = new HttpTarget(8080);

    @DefaultRequestValues
    public void defaultRequestValues(PactDslRequestWithoutPath request) {
        Map<String, String> headers = new HashMap<>();
        headers.put(HttpHeaders.AUTHORIZATION, UserControllerIT.AUTH_TOKEN1);
        request.headers(headers);

        System.out.println("THIS IS NEVER CALLED");
    }

    @State("User with id NOPE does not exist")
    public void userWithIdNopeDoesNotExist_andServerRunning() {
        String[] args =  new String[1];
        args[0] = ""; //don't ask
        SpringApplication.run(UserServiceApplication.class, args);
    }

}

The defaultRequestValues method is never called, the authorization header is never set, and the service returns 401 (which is correct behavior in this case but that's not what I'm trying to test).

Any ideas how I can set the authorization header on this test? Thanks.


Solution

  • Well, no, it wouldn't run because you're using the @State to run your "test" where the state is meant to only setup the state and not run your test code. Pact needs a way to be able to intercept the request and add those defaults to every one of them, this is why we you need to setup the interactions and return them to the framework so those interactions are added the defaults.

    The best example I can give you is this test that we have that tests this the default request values. You'll notice that the createFragment function returns a RequestResponsePact object. This is the interaction that you're about to test which the defaults get added to.