- Get Started
- Product
- Resources
- Tools & SDKs
- Framework
- Reference
- Get Started
- Product
- Resources
- Tools & SDKs
- Framework
- Reference
6.2.1. Example: Write Integration Tests for API Routes
In this chapter, you'll learn how to write integration tests for API routes using the medusaIntegrationTestRunner utility function.
Test a GET API Route#
Consider the following API route created at src/api/custom/route.ts
:
To write an integration test that tests this API route, create the file integration-tests/http/custom-routes.spec.ts
with the following content:
1import { medusaIntegrationTestRunner } from "@medusajs/test-utils"2 3medusaIntegrationTestRunner({4 testSuite: ({ api, getContainer }) => {5 describe("Custom endpoints", () => {6 describe("GET /custom", () => {7 it("returns correct message", async () => {8 const response = await api.get(9 `/custom`10 )11 12 expect(response.status).toEqual(200)13 expect(response.data).toHaveProperty("message")14 expect(response.data.message).toEqual("Hello, World!")15 })16 })17 })18 },19})20 21jest.setTimeout(60 * 1000)
You use the medusaIntegrationTestRunner
to write your tests.
You add a single test that sends a GET
request to /custom
using the api.get
method. For the test to pass, the response is expected to:
- Have a code status
200
, - Have a
message
property in the returned data. - Have the value of the
message
property equal toHello, World!
.
Run Tests#
Run the following command to run your tests:
This runs your Medusa application and runs the tests available under the src/integrations/http
directory.
Jest Timeout#
Since your tests connect to the database and perform actions that require more time than the typical tests, make sure to increase the timeout in your test:
Test a POST API Route#
Suppose you have a hello
module whose main service extends the service factory, and that has the following model:
And consider that the file src/api/custom/route.ts
defines another route handler for POST
requests:
1// other imports...2import HelloModuleService from "../../../modules/hello/service"3 4// ...5 6export async function POST(7 req: MedusaRequest,8 res: MedusaResponse9) {10 const helloModuleService: HelloModuleService = req.scope.resolve(11 "helloModuleService"12 )13 14 const myCustom = await helloModuleService.createMyCustoms(15 req.body16 )17 18 res.json({19 my_custom: myCustom,20 })21}
This API route creates a new record of MyCustom
.
To write tests for this API route, add the following at the end of the testSuite
function in integration-tests/http/custom-routes.spec.ts
:
1// other imports...2import HelloModuleService from "../../src/modules/hello/service"3 4medusaIntegrationTestRunner({5 testSuite: ({ api, getContainer }) => {6 describe("Custom endpoints", () => {7 // other tests...8 9 describe("POST /custom", () => {10 const id = "1"11 12 it("Creates my custom", async () => {13 14 const response = await api.post(15 `/custom`,16 {17 id,18 name: "Test",19 }20 )21 22 expect(response.status).toEqual(200)23 expect(response.data).toHaveProperty("my_custom")24 expect(response.data.my_custom).toEqual({25 id,26 name: "Test",27 created_at: expect.any(String),28 updated_at: expect.any(String),29 })30 })31 })32 })33 },34})
This adds a test for the POST /custom
API route. It uses api.post
to send the POST request. The api.post
method accepts as a second parameter the data to pass in the request body.
The test passes if the response has:
- Status code
200
. - A
my_custom
property in its data. - Its
id
andname
match the ones provided to the request.
Tear Down Created Record#
To ensure consistency in the database for the rest of the tests after the above test is executed, utilize Jest's setup and teardown hooks to delete the created record.
Use the getContainer
function passed as a parameter to the testSuite
function to resolve a service and use it for setup or teardown purposes
So, add an afterAll
hook in the describe
block for POST /custom
:
1// other imports...2import HelloModuleService from "../../src/modules/hello/service"3 4medusaIntegrationTestRunner({5 testSuite: ({ api, getContainer }) => {6 describe("Custom endpoints", () => {7 // other tests...8 9 describe("POST /custom", () => {10 // ...11 afterAll(() => async () => {12 const helloModuleService: HelloModuleService = getContainer().resolve(13 "helloModuleService"14 )15 16 await helloModuleService.deleteMyCustoms(id)17 })18 })19 })20 },21})
The afterAll
hook resolves the HelloModuleService
and use its deleteMyCustoms
to delete the record created by the test.
Test a DELETE API Route#
Consider a /custom/:id
API route created at src/api/custom/[id]/route.ts
:
1import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"2import HelloModuleService from "../../../modules/hello/service"3 4export async function DELETE(5 req: MedusaRequest,6 res: MedusaResponse7) {8 const helloModuleService: HelloModuleService = req.scope.resolve(9 "helloModuleService"10 )11 12 await helloModuleService.deleteMyCustoms(req.params.id)13 14 res.json({15 success: true,16 })17}
This API route accepts an ID path parameter, and uses the HelloModuleService
to delete a MyCustom
record by that ID.
To add tests for this API route, add the following to integration-tests/http/custom-routes.spec.ts
:
1medusaIntegrationTestRunner({2 testSuite: ({ api, getContainer }) => {3 describe("Custom endpoints", () => {4 // ...5 6 describe("DELETE /custom/:id", () => {7 const id = "1"8 9 beforeAll(() => async () => {10 const helloModuleService: HelloModuleService = getContainer().resolve(11 "helloModuleService"12 )13 14 await helloModuleService.createMyCustoms({15 id,16 name: "Test",17 })18 })19 20 it("Deletes my custom", async () => {21 const response = await api.delete(22 `/custom/${id}`23 )24 25 expect(response.status).toEqual(200)26 expect(response.data).toHaveProperty("success")27 expect(response.data.success).toBeTruthy()28 })29 })30 })31 },32})
This adds a new test for the DELETE /custom/:id
API route. You use the beforeAll
hook to create a MyCustom
record using the HelloModuleService
.
In the test, you use the api.delete
method to send a DELETE
request to /custom/:id
. The test passes if the response:
- Has a
200
status code. - Has a
success
property in its data. - The
success
property's value is true.