Skip to content

Instantly share code, notes, and snippets.

@mustafadalga
Created October 25, 2023 14:29
Show Gist options
  • Save mustafadalga/7c4919b5896bd91ee12c0e90dca1b3ce to your computer and use it in GitHub Desktop.
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.
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);
})
})
})
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 });
}
}
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);
});
})
})
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