Testing responses
Once you've written your triggers, you'll need to write either a
testResponse
or a testErrorResponse
function.
These are used to confirm that your client understood the response from the server. These functions are separate from the trigger so that ContractCase can tell the difference between a problem in your client code and a problem in the verification of the object returned from your client code.
Test Response Function
Use this if your client code is expected to succeed during this interaction.
In a test response function, you should assert that your client code has successfully understood the response and marshalled it into whatever business object the rest of your code expects.
Test Error Response Function
Use this if your client code is expected to complete with an exception / rejected promise during an interaction.
In a test error response function, you should assert that your client code has correctly understood the response and marshalled it into whatever failed exception / error object the rest of your code expects.
testErrorResponse: (error: Error, config: MockConfig): Promise<unknown> | void
This is equivalent to the testResponse
function, but for trigger
calls that are expected to fail with an error.
With runInteraction
If we define this example at the client side, we will also need a trigger, and a way to test the response object:
await contract.runInteraction({
states: [
inState('Server is up'),
inState('A user with id "foo" exists'),
],
definition: willSendHttpRequest({
request: {
method: 'GET',
path: '/users/foo',
},
response: {
status: 200,
body: {
userId: 'foo'
name: 'john smith',
},
},
}),
},
{
// The trigger is the invocation of your client code
// It receives some configuration with details of how to contact the mock
// This function should return the business object that your API returns
trigger: (config: HttpRequestConfig) =>
new YourApi(config.baseUrl).getUser('foo'),
// The testResponse function is used to check the business object.
// This is an important step, as without it, ContractCase can't be sure that your
// calling code can understand the objects that your code is generating.
//
// It receives the object that was returned by your trigger
// If your trigger throws an error, the test will fail
testResponse: (user) => {
expect(user).toEqual({ userId: 'foo', name: 'john smith' });
}
})
With runRejectingInteraction
If your API is expected to throw an error during the invocation, then you should use runRejectingInteraction
instead of runInteraction
, and use testErrorResponse
instead of testResponse
:
await contract.runRejectingInteraction(
{
states: [inState('Server is up'), inState('No users exist')],
definition: willSendHttpRequest({
request: {
method: 'GET',
path: '/users/foo',
},
response: {
status: 404,
},
}),
},
{
// The trigger is the invocation of your client code
// It receives some configuration with details of how to contact the mock
// This function should return the business object that your API returns
trigger: (config: HttpRequestConfig) =>
new YourApi(config.baseUrl).getUser('foo'),
// The testErrorResponse function is used to check the business object.
// This is an important step, as without it, ContractCase can't be sure that your
// calling code can understand the objects that your code is generating.
//
// It receives the object that was thrown by your trigger.
// If your trigger does not throw an error, the test will fail
testErrorResponse: (e) => {
expect(e).toBeInstanceOf(UserNotFoundError);
},
},
);
Triggers and testResponse
/testErrorResponse
functions are not written to the contract.