A powerful and type-safe fetch mocking library designed specifically for Bun tests. Mock HTTP requests with ease and full TypeScript support.
- π Built for Bun test runner
- π Full TypeScript support with strict typing
- π Support for all HTTP methods (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS)
- π Custom response status codes, headers, and content types
- π― Fluent API with method chaining
- β Built-in assertion helpers
- π One-time and persistent mocks
- π‘οΈ Input validation and helpful error messages
bun install bun-fetch-mock
import { test, expect } from "bun:test";
import { useFetchMock } from "bun-fetch-mock";
test("API call returns user data", async () => {
const fetchMock = useFetchMock({ baseUrl: "https://api.example.com" });
// Setup mock
fetchMock.get("/users/1", {
data: { id: 1, name: "John Doe", email: "john@example.com" },
status: 200
});
// Your code that makes the fetch call
const response = await fetch("https://api.example.com/users/1");
const user = await response.json();
expect(user.name).toBe("John Doe");
fetchMock.assertAllMocksUsed();
});
Creates a new fetch mock instance with automatic setup and teardown.
const fetchMock = useFetchMock({
baseUrl: "https://api.example.com" // Optional base URL
});
All methods support the same options and return the mock instance for chaining.
fetchMock.get(url, opts?)
fetchMock.post(url, opts?)
fetchMock.put(url, opts?)
fetchMock.delete(url, opts?)
fetchMock.patch(url, opts?)
fetchMock.head(url, opts?)
fetchMock.options(url, opts?)
interface MockOpts<T> {
data?: T; // Response data (JSON or string)
status?: number; // HTTP status code (default: 200)
headers?: Record<string, string>; // Response headers
statusText?: string; // Status text (default: "OK")
once?: boolean; // If true, mock is removed after first use
}
fetchMock.get("/api/users", {
data: [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }]
});
fetchMock.post("/api/users", {
data: { id: 3, name: "Charlie" },
status: 201,
headers: { "Location": "/api/users/3" },
statusText: "Created"
});
fetchMock.get("/api/health", {
data: "OK",
headers: { "Content-Type": "text/plain" }
});
fetchMock.get("/api/data", {
data: { message: "This mock will be removed after first use" },
once: true
});
fetchMock.get("/api/error", {
data: { error: "Not found" },
status: 404,
statusText: "Not Found"
});
fetchMock.head("/api/check", {
status: 200,
headers: { "X-Resource-Count": "42" }
});
Clears all mocks:
fetchMock.reset();
Asserts that all mocks have been called (useful in test cleanup):
test("all mocks are used", async () => {
fetchMock.get("/api/data", { data: "test" });
await fetch("/api/data");
fetchMock.assertAllMocksUsed(); // Passes
});
fetchMock
.get("/api/data", { data: "first call", once: true })
.get("/api/data", { data: "subsequent calls" });
fetchMock
.get("/users", { data: users })
.post("/users", { data: newUser, status: 201 })
.delete("/users/1", { status: 204 });
const fetchMock = useFetchMock({ baseUrl: "https://api.example.com" });
// These are equivalent:
fetchMock.get("/users", { data: users });
// Mocks: https://api.example.com/users
// Or use full URLs:
fetchMock.get("https://api.example.com/users", { data: users });
# Install dependencies
bun install
# Run type checking
bun run type-check
# Run linting
bun run lint
- Bun >= 1.0.0
- TypeScript (for development)
MIT