4

I'm starting to use Pact (on Java) for Contract Tests.

I've read Contract Tests vs Functional Tests on Pact best practices but I'm a little confused.

Example: a simple REST endpoint that creates a resource (POST), returning a 201 Created on success and 400 Bad Request for syntactic validation errors. The request body is something like:

{
    "firstname" : "Foo",
    "lastname" : "Bar"
}

Both firstname and lastname must not be blank. So far as I understand I could write 3 scenarios here, in which the provider should return 400 Bad Request:

  1. firstname is blank, lastname is not blank
  2. firstname is not blank, lastname is blank
  3. firstname and lastname are both blank

The thing is that the mock server returns a 500 Internal Server Error if only the "happy path pact" is defined, and if I want to make it return 400 Bad Request I have to write all possible pacts. Moreover, if I add another fields with the same validation rule the number of pacts explodes.

  • First of all, should I test that scenarios on my consumer?
  • If yes, do exists any smart way to implement it with Pact DSL?

Thank you.

2 Answers2

4

When I’m establishing a contract for a POST, I care about the server accepting a valid input and the way the server responds (usually 400) to a bad input. There’s no need to have a contract for all the possible ways an input might be invalid, mainly because this can happen for an uncountable number of reasons.

So, I, from a consumer perspective, typically have only one interaction for invalid inputs, unless I’m facing a very particular situation where the server might respond differently depending on the reason of the failure, and I care about the different responses.

For your specific situation, write a contract for just one of the three mentioned scenarios.

Édouard Lopez
  • 40,270
  • 28
  • 126
  • 178
Fabricio Lemos
  • 2,905
  • 2
  • 31
  • 31
2

The core message of the Functional vs Contract discussion in your case is this: those permutations of unhappy paths belong in your Provider code, because that is where the logic is.

As @fabricio-lemos puts it, you just need to encapsulate a single example of a 400 bad request to prove that your code can handle that case.

As for the 500 error, that is possibly because you are not setting up a single expected interaction (via the Pact DSL) per test. If you hit the Pact mock server before the expected interaction has been registered, you get the 500.

In pseudo-code your test structure might look like

Describe "User API"
  BeforeAll
     setup Pact mock server
  AfterEach
     verify and clear interactions 
  With valid request
     setup 201 interaction
     run tests
  With invalid request
     setup 400 interaction
     run tests 
Matthew Fellows
  • 3,669
  • 1
  • 15
  • 18