Created
October 25, 2023 14:29
-
-
Save mustafadalga/7c4919b5896bd91ee12c0e90dca1b3ce to your computer and use it in GitHub Desktop.
Demonstration of unit testing for Next.js 13 API routes, covering GET and POST methods with mocks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { describe, it, expect, vi } from "vitest"; | |
import { createRequest } from 'node-mocks-http'; | |
import { GET } from "./route"; | |
const mocks = vi.hoisted(() => ({ | |
get: vi.fn(), | |
})); | |
vi.mock("axios", async () => { | |
const actual: any = await vi.importActual("axios"); | |
return { | |
default: { | |
...actual.default, | |
create: vi.fn(() => ({ | |
...actual.default.create(), | |
get: mocks.get, | |
})), | |
}, | |
}; | |
}); | |
describe("Clients API Route", () => { | |
describe("GET", () => { | |
const mockPost = [ { | |
"userId": 1, | |
"id": 2, | |
"title": "qui est esse", | |
"body": "est rerum tempore vitaeequi sint nihil reprehenderit dolor beatae ea dolores nequeugiat blanditiis voluptate porro vel nihil molestiae ut reiciendisqui aperiam non debitis possimus qui neque nisi nulla" | |
} ] | |
const request = createRequest({ | |
method: 'GET', | |
cookies: { | |
get: vi.fn().mockReturnValue({ value: 'mockJwtToken' }) as any, | |
} | |
}); | |
it("should return a list of post", async () => { | |
mocks.get.mockResolvedValueOnce({ data: mockPost }); | |
const response = await GET(request); | |
const responseJson = await response.json(); | |
expect(responseJson).toEqual(mockPost); | |
expect(response.status).toBe(200); | |
}) | |
it("should return an error message when the API call fails", async () => { | |
mocks.get.mockRejectedValueOnce({ data: mockPost }); | |
const response = await GET(request); | |
const responseJson = await response.json(); | |
const expectedErrorMessage = "Oops! Something went wrong while loading posts. Please refresh the page and try again!"; | |
expect(responseJson.message).toEqual(expectedErrorMessage); | |
expect(response.status).not.toBe(200); | |
}) | |
}) | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { NextRequest, NextResponse } from "next/server"; | |
import { AxiosInstance } from "axios"; | |
import { CookieKeys } from "@/_enums"; | |
import createAuthenticatedApiServiceV2 from "@/_services/createAuthenticatedApiServiceV2"; | |
import handleAxiosError from "@/_utilities/handleAxiosError"; | |
export async function GET(request: NextRequest) { | |
// Retrieve JWT token from cookies | |
const jwt: string | undefined = request.cookies.get(CookieKeys.Jwt)?.value; | |
// Create an authenticated API service instance using the JWT token | |
const api: AxiosInstance = createAuthenticatedApiServiceV2(jwt); | |
if (request.method !== "GET") { | |
return NextResponse.json({ message: "Method not allowed" }, { status: 405 }) | |
} | |
try { | |
const { data } = await api.get("/posts"); | |
return NextResponse.json(data, { status: 200 }); | |
} catch (error) { | |
const { | |
message, | |
status, | |
details | |
} = handleAxiosError(error, "Oops! Something went wrong while loading posts. Please refresh the page and try again!"); | |
return NextResponse.json({ message, details }, { status }); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { describe, it, expect, vi } from "vitest"; | |
import { createRequest } from 'node-mocks-http'; | |
import { POST } from "./route"; | |
const mocks = vi.hoisted(() => ({ | |
post: vi.fn(), | |
})); | |
vi.mock("axios", async () => { | |
const actual: any = await vi.importActual("axios"); | |
return { | |
default: { | |
...actual.default, | |
create: vi.fn(() => ({ | |
...actual.default.create(), | |
post: mocks.post, | |
})), | |
}, | |
}; | |
}); | |
describe("Datasources API Route", () => { | |
describe("POST", () => { | |
const request = createRequest({ | |
method: 'POST', | |
cookies: { | |
get: vi.fn().mockReturnValue({ value: 'mockJwtToken' }) as any, | |
}, | |
json: vi.fn().mockResolvedValue({ clientID: '1' }) | |
}); | |
const mockPost = { | |
"userId": 1, | |
"id": 2, | |
"title": "qui est esse", | |
"body": "est rerum tempore vitaeequi sint nihil reprehenderit dolor beatae ea dolores nequeugiat blanditiis voluptate porro vel nihil molestiae ut reiciendisqui aperiam non debitis possimus qui neque nisi nulla" | |
} | |
it("should create a post", async () => { | |
mocks.post.mockResolvedValueOnce({ data: mockPost }); | |
const response = await POST(request); | |
const responseJson = await response.json(); | |
expect(responseJson).toEqual(mockPost); | |
expect(response.status).toBe(200); | |
}); | |
it("should return an error message when the API call fails", async () => { | |
mocks.post.mockRejectedValueOnce({ data: mockPost }); | |
const response = await POST(request); | |
const responseJson = await response.json(); | |
const expectedErrorMessage = "Oops! Something went wrong while creating post. Please refresh the page and try again!"; | |
expect(responseJson.message).toBe(expectedErrorMessage); | |
expect(response.status).not.toBe(200); | |
}); | |
}) | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { NextRequest, NextResponse } from "next/server"; | |
import { AxiosInstance } from "axios"; | |
import { CookieKeys } from "@/_enums"; | |
import createAuthenticatedApiServiceV2 from "@/_services/createAuthenticatedApiServiceV2"; | |
import handleAxiosError from "@/_utilities/handleAxiosError"; | |
interface IDataSource { | |
email: string; | |
name: string; | |
sourceType: string; | |
clientID: string; | |
status: boolean | |
} | |
export async function POST(request: NextRequest) { | |
const jwt: string | undefined = request.cookies.get(CookieKeys.Jwt)?.value; | |
const api: AxiosInstance = createAuthenticatedApiServiceV2(jwt); | |
if (request.method !== "POST") { | |
return NextResponse.json({ message: "Method not allowed" }, { status: 405 }) | |
} | |
try { | |
const bodyData = await request.json(); | |
const { data } = await api.post<IDataSource[]>("/post/create", { | |
data:bodyData | |
},); | |
return NextResponse.json(data, { status: 200 }); | |
} catch (error) { | |
const { | |
message, | |
status, | |
details | |
} = handleAxiosError(error, "Oops! Something went wrong while creating post. Please refresh the page and try again!"); | |
return NextResponse.json({ message, details }, { status }); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment