In the previous section, Contract testing, we discussed things in detail. In this section, we will see how we can implement consumer-driven contract tests with the help of pact-net-core.
We will use our existing FlixOne.BookStore.ProductService project, which contains all our APIs. Our FlixOne.BookStore.ProductService project contains provider tests that let you create a provider scenario, and our client project that actually consumes the services, makes a call, and tests the contract.
As per Pact specification (already discussed in a previous section, Contract testing), the client will create a contract called consumer contract (a .json file). We have written the following code to generate our contract:
public class ConsumerProductApi : IDisposable
{
public ConsumerProductApi()
{
PactBuilder = new PactBuilder(new PactConfig
{
SpecificationVersion = Constant.SpecificationVersion,
LogDir = Helper.SpecifyDirectory(Constant.LogDir),
PactDir = Helper.SpecifyDirectory(Constant.PactDir)
})
.ServiceConsumer(Constant.ConsumerName)
.HasPactWith(Constant.ProviderName);
MockProviderService = PactBuilder.MockService
(Constant.Port, Constant.EnableSsl);
}
public IPactBuilder PactBuilder { get; }
public IMockProviderService MockProviderService { get; }
public string ServiceBaseUri => $"http://localhost:{Constant.Port}";
public void Dispose()
{
PactBuilder.Build();
}
}
In the preceding code, we are building a contract. In addition to that, we mocked our client tests. See the following code snippet:
[Fact]
public void WhenApiIsUp_ReturnsTrue()
{
//Arrange
_mockProviderService.UponReceiving("a request to
check the api status")
.With(new ProviderServiceRequest
{
Method = HttpVerb.Get,
Headers = new Dictionary<string, object> { { "Accept",
"application/json" } },
Path = "/echo/status"
})
.WillRespondWith(new ProviderServiceResponse
{
Status = 200,
Headers = new Dictionary<string, object> { {
"Content-Type", "application/json; charset=utf-8" } },
Body = new
{
up = true,
upSince = DateTime.UtcNow,
version = "2.0.0",
message = "I'm up and running from last 19 hours."
}
});
var consumer = new ProductApiClient(_serviceBaseUri);
//Act
var result = consumer.ApiStatus().Up;
//Assert
Assert.True(result);
_mockProviderService.VerifyInteractions();
}
Our code will create the consumer contract as shown in the following:
{
"consumer":
{
"name": "Product API Consumer"
},
"provider":
{
"name": "Product API"
},
"interactions":
[
{
"description": "a request to check the api status",
"request":
{
"method": "get",
"path": "/echo/status",
"headers":
{
"Accept": "application/json"
}
},
"response":
{
"status": 200,
"headers":
{
"Content-Type": "application/json; charset=utf-8"
},
"body":
{
"up": true,
"upSince": "2017-11-06T00:52:01.3164539Z",
"version": "2.0.0",
"message": "I'm up and running from last 19 hours."
}
}
}
],
"metadata":
{
"pactSpecification":
{
"version": "2.0.0"
}
}
}
Once the consumer-driven contract is created, it should adhere to a provider, so we need to write the APIs accordingly (we are using our existing product API). The following is the code snippet for a provider:
//Arrange
const string serviceUri = "http://localhost:13607";
var config = new PactVerifierConfig
{
Outputters = new List<IOutput>
{
new CustomOutput(_output)
}
};
//code omitted
We have created a web API and a test to verify consumer-driven contracts and finally testing it from a client's perspective.