Reputation: 472
We are running a microservice architecture and want to set up contract testing in our project. Our consumers do not know which request is handled by which microservice. We want our microservices to select the interactions from the pacts that they should participate in.
Example:
POST /users
.POST /users
with different parameters.GET /users/$userId
.GET /articles/$articleId
.POST /users
requests.GET /users/$userId
requests.GET /articles/$articleId
requests.We want to put provider tests next to the Microservices. Each microservice should only test the endpoints that it is capable of handling. In this scenario, Microservice A would test all of the POST /users
contracts. Microservice B would select the GET /users/$userId
contracts and so on.
Is there a way to do so with pactflow.io and nodejs bindings for pact?
Edit: Added the architecture diagram:
Upvotes: 0
Views: 348
Reputation: 472
We have found a solution to our particular problem:
We define a provider as the tuple (HTTP method, URL). As a result, a consumer contains many tests for many providers and a microservice also contains many tests for many providers.
Something like this in node.js for the consumer:
const consumer = "MyConsumer";
const providerGetArticles = new Pact({ consumer, provider: 'GET-articles', ... });
const providerGetArticlesArticleId = new Pact({ consumer, provider: 'GET-articles-:articleId', ... });
const providerPostUsers = new Pact({ consumer, provider: 'POST-users', ... });
const providerGetUsers = new Pact({ consumer, provider: 'GET-users', ... });
const providerGetUsersUserId = new Pact({ consumer, provider: 'GET-users-:userId', ... });
providerGetArticles.setup().then(() => {
providerGetArticles.addInteraction(
{
withRequest: { method: 'GET', path: '/articles' },
...
providerGetArticlesArticleId.setup().then(() => {
providerGetArticlesArticleId.addInteraction(
{
withRequest: { method: 'GET', path: '/articles/12345' },
...
providerPostUsers.setup().then(() => {
providerPostUsers.addInteraction(
{
withRequest: { method: 'POST', path: '/users' },
...
And like this for a microservice that handles GET /articles
and GET /articles/:articleId
new Verifier({ provider: 'GET-articles', ... }).verifyProvider()...
new Verifier({ provider: 'GET-articles-:articleId', ... }).verifyProvider()...
We can now start the single microservice in isolation and run the provider tests.
Upvotes: 0
Reputation: 4065
No, there is no such in-built feature in Pact that supports that use case.
We've discussed the possibility of publishing expectations for messages this way, but not HTTP (because this is a bit more unusual, unlike message queues like Kafka where there is usually more indirection).
Are you using some form of dynamic API gateway or something?
One challenge you'll face is reverse engineering out the requests themselves in a reliable manner.
Ideas
The only suggestion I have would be to have a proxy on the provider side test that was aware of the different endpoints, and would redirect the requests to the correct provider. But then state handling gets difficult.
You can of course also manually fetch the pacts, and split them, but you'll lose a lot of value that pact has.
I'm not sure if the consumers not knowing about the providers is more of a philosophical thing, a practical thing or otherwise, but obviously the simplest solution is probably making the consumers aware of their providers.
Raise a Feature Request
Perhaps stating your use case more clearly and requesting a feature at https://pact.canny.io/ might be worthwhile, to see how relevant your use case is to the broader community and if it would be worth implementing.
Upvotes: 1