Kafka Mocking with AsyncAPI using Specmatic
Channel: ConfEngine
Date: 2023-07-18

Learn more about Specmatic and Contract Driven Development: https://specmatic.io

Sample project: https://github.com/znsio/specmatic-order-bff-nodejs
Download Specmatic: https://github.com/znsio/specmatic/releases

Transcript:
In this video, we'll show you how Kafka can be mocked out using Specmatic. Let's take the example of an HTTP consumer that sends a request to an application. The request is received by the controller, which invokes a service layer that fetches data from an HTTP API dependency and then drops the message onto a Kafka topic. The service layer returns a response to the controller, which in turn returns a response to the consumer. Now, to test this application in isolation, we take an AsyncAPI specification that defines the format for messages on the Kafka topic and mock it out using Specmatic's Kafka mock. Let's say we also use Specmatic to run contract tests against the application. First, Specmatic must set expectations with the Kafka mock about messages that it will receive. Then it must set expectations on a Specmatic HTTP stub that has the OpenAPI specification of the HTTP dependency. You can learn more about contract testing and HTTP stubbing with Specmatic in other videos. Finally, Specmatic  uses the application's OpenAPI specification to run contract tests against it. Each contract test sends a request to the application which is received by the controller, which in turn invokes the service layer.

The service layer fetches data from the HTTP service stub and drops a message onto the topic on the Kafka mock. The Kafka mock uses an in memory Kafka broker, so the service layer sends messages to it seamlessly, just like to a production instance of Kafka. The service layer responds to the controller, which in turn responds to the contract test. After the contract tests run, Specmatic asks the Kafka mock to verify the messages that it received. Let's see this in an actual example. Here's an application that fetches data from an HTTP API and writes a message to a Kafka broker. Here's specmatic.json in which we provide the AsyncAPI specification for marking out the Kafka dependency, the OpenAPI specification for stubbing out the HTTP dependency which the application needs, and the OpenAPI specification of the application itself which Specmatic will use to run contract tests. Here's the AsyncAPI specification for the Kafka dependency, and here we see the message schema definition for the product queries topic. Now let's run the contract tests.

Here you go. The test suite has passed. Let's look at the API coverage summary. We have a contract test for one of the APIs, but not for the other, and so it's marked as missed.

Let's look at how the Kafka expectations are being set and verified. After starting the Specmatic Kafka mock, we set an expectation that it would receive a single message on the product queries topic. When the test runs, any messages received on this topic are validated against the product queries message schema in the AsyncAPI specification. Finally, we call the verify Kafka mock method. This checks if as per expectations, the mock has received a single message at the product queries topic, and if that message adhered to the AsyncAPI specification. If either of these conditions are not met or say if a topic not in any specification received a message, the Verify Kafka mock method returns an error.

The set up for API tests is on similar lines to the Specmatic contract tests. Let's run the tests. All right, these tests have passed as well. Let's take a quick look at the test set up. Like with the contract tests, we start a Kafka mock, and then we set an expectation that a single message is expected on the product queries topic. Then in the test, we verify that the required message has indeed been received.

Here, we specify the message that we expect, and the verification will fail if this exact message has not been received on the product queries topic. Then here, we verify that only one message on the product queries topic has been received as defined by the expectation set earlier on. Message verification lets the test keep a tight rein on all Kafka messages sent by the application. Since the mock is wire compatible and entirely within the control of the test, the test can run locally and in CI and deliver quick feedback early in the cycle.