Eg. A -> B -> C
A more find grained view of this intergration might go:
|------------------A Codebase------------------||------------------B Codebase------------------||--------C Codebase---...
A UI -> A Controller -> B Service -> B Client -> B API -> B Controller -> CService -> CClient -> C API etc...
|---A/B pact------------------------?
|---A/B pact------------------------------------?
|---A/B pact----------------------------------------------?
The recommended approach for creating the A/B Pact is to write Pact tests for the BClient class (testing the "back door" of A and the "front door" of B). When you verify the A/B Pact, it's best to stub out the calls to C at some level. You may choose to stub at the Service, Client or API (HTTP) level. Which ever level you choose, you then need to make sure that you have another test that ensures that the real compontent behaves the same way as the stubbed component, just like Pact all over again. You'll need some sort of "contract" to keep those tests in sync, whether that contract is another Pact, or a "shared artifact" (more on that below).
Assuming that all your interactions between B and C go through a "CClient" class, you can create a stub implementation of CClient that allows you to set arbitrary responses during your provider state set up call.
class CClientStubImpl implements CClient {
private Alligator alligator;
public void stubAlligator(Alligator alligator) {
this.alligator = alligator;
}
@Override
public Alligator getAlligator(String name) {
return alligator;
}
}
class CStubbedObjects {
public static final Alligator MARY = new Alligator("Mary");
}
During provider state set up:
cclient.stubAlligator(CStubbedObjects.MARY);
Then, in your Pact test for CClient, you can use the same alligator instance as a "link" to tie your stubbing to an artifact that will get verified.
Ron can you give me an example for pact jvm or groovy?
A pact is best created using unit tests for the client class. Ideally, you could have a CClient in your B codebase, and you would write your Pact tests using that CClient class.
Once you have generated that pact in the B unit tests, it can than be used with one of the Pact stub server
implementations to run up an HTTP mock during the A/B verification.
One thing to beware of with this approach is that you'll want to use the type/regular expression based matching (the "flexible" matching) when you set up your expected requests in your B/C Pact tests. Usually, we would advise that your request expectations use exact values, as you're in full control of the HTTP request that is sent to the mock server in a unit test. However, if your outgoing request to C is being generated from your incoming request from A during a Pact verification, you can't control what is going to be in that request, so you'll want to be as flexible as possible.
Do you need me to provide an example of using a mock client, or an example of a "link" to tie your stubbing to an artifact that will get verified?
I haven't had much success with using option 2. The problem is the data used in the Pact between B and C could be very different as from that from A to B. And you want to avoid coupling your tests together with common data.