Testing API Functions
In our workflow repo, the register function makes an API call to create a new user account:
// auth.js
import { URL } from "../../constants/api.js";
export async function register(user) {
const url = `${URL}auth/register`;
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(user),
};
const response = await fetch(url, options);
const json = await response.json();
if (!response.ok) {
throw new Error("Registration failed");
}
return json;
}
This function:
- Takes a user object with registration details
- Makes a POST request to the registration endpoint
- Returns the new user data if successful
- Throws an error if the request fails
Testing Success and Failure
Just like in lesson 4, we’ll use a mock fetch function to test both successful and failed registration:
import { expect, describe, it, beforeEach } from "vitest";
import { register } from "./auth";
describe("register", () => {
beforeEach(() => {
global.fetch = vi.fn();
});
it("returns the user data when registration succeeds", async () => {
const successResponse = {
id: 1,
name: "John Smith",
email: "john@stud.noroff.no",
};
fetch.mockResolvedValue({
ok: true,
json: () => Promise.resolve(successResponse),
});
const result = await register({
name: "John Smith",
email: "john@stud.noroff.no",
password: "password123",
});
expect(result).toEqual(successResponse);
});
it("throws an error when registration fails", async () => {
fetch.mockResolvedValue({
ok: false,
json: () => Promise.resolve({ message: "Email already exists" }),
});
await expect(
register({
name: "John Smith",
email: "john@stud.noroff.no",
password: "password123",
})
).rejects.toThrow("Registration failed");
});
});
Let’s break down what we’re testing:
Success case:
- Mock fetch to return a successful response
- Call register with user details
- Verify we get back the expected user data
Failure case:
- Mock fetch to return a failed response
- Call register with user details
- Verify it throws the expected error
Note that we’re testing the function’s behavior (what it returns or throws) rather than implementation details (like what URL it calls).
What We Learned
- Used mocks to test functions that make API calls
- Tested both successful and failed API responses
- Focused on testing behavior rather than implementation details
- Used beforeEach to reset our mocks between tests