This article is a part of the series "Generating applications from an OpenAPI spec"
- Why use OpenAPI?
- Generating application and client code from an OpenAPI spec
- Generating MSW mocks from an OpenAPI spec.
- Using Postman and an OpenAPI spec for contract/blackbox tests
- Postman and OpenAPI - Automating tests
- OpenAPI and contract tests with Jest
- Blackbox contract tests - Performance testing with Jest
- Black box contract testing - third party API mocking
Generating MSW mocks from an OpenAPI spec.
A commonly suggested approach for testing frontend code is to use a tool like Mock Service Worker to mock your HTTP requests.
In this post, we'll demonstrate usage of the tool msw-auto-mock to achieve this, and save us writing screeds of mocking logic ourselves.
All code for this example can by found here.
Our component
export const DisplayPetById = (props: DisplayPetByIdProps) => {
const { } = props;
const petQuery = usePet(props.petId);
return (
<div>
{petQuery.isLoading && "...loading"}
{petQuery.isError && "Error!"}
{petQuery.data && <>
Pet Name: {petQuery.data.name}
</>}
</div>
);
};
We have a simple component here. That usePet
looks like this:
import { useQuery } from "@tanstack/react-query";
import { petsApi } from "../services/petsService";
export function usePet(petId:number){
return useQuery({
queryFn: () => petsApi.findPetById({ id: petId}),
queryKey: ["pet", petId],
});
}
We're using react-query to provide loading flags etc, and we're using that service function that created in our earlier post.
The Test
We make sure we have included an example in our OpenAPI definition:
//Pet.json
{
"type": "object",
"required": [
"id",
"name"
],
"properties": {
"id": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string",
+ "example" : "Fido"
},
"tag": {
"type": "string"
}
}
}
We can now run:
msw-auto-mock ../spec/petstore-separate/spec/swagger.json \
-o src/generated/msw.js --base-url '/api'
And hey presto, all of the MSW boiler plate is created in that msw.js
output file we generated.
Our test:
import React from 'react';
// We have our render method which includes the react-query provider
import {render} from "../testUtils/testRender";
import {screen} from "@testing-library/react";
import {DisplayPetById} from './DisplayPetById';
// Import handlers from the generated MSW boilerplate
import {handlers} from "../generated/msw";
import { setupServer } from 'msw/lib/node';
const server = setupServer(...handlers);
describe(DisplayPetById, () => {
beforeAll(() => {
// Establish requests interception layer before all tests.
server.listen()
})
afterAll(() => {
// Clean up after all tests are done, preventing this
// interception layer from affecting irrelevant tests.
server.close()
})
it("Renders without error", async () => {
render(<DisplayPetById petId={1}/>)
expect(screen.getByText("...loading")).toBeInTheDocument();
// The pet name is based on the example we set in the OpenAPI definition!
expect(await screen.findByText("Pet Name: Fido")).toBeInTheDocument();
});
});
Brilliant!
msw-auto-mock does not currently support multiple examples, which might make this limiting for more comprehensive testing. In that case you might need to get creative and/or extend the functionality of what msw-auto-mock is providing.
Questions? Comments? Criticisms? Get in the comments! 👇
Spotted an error? Edit this page with Github