Bun Test Mocking
Bun provides Jest-compatible mocking with mock() , spyOn() , and module mocking.
Mock Functions
import { test, expect, mock } from "bun:test";
// Create mock function const fn = mock(() => "original");
test("mock function", () => { fn("arg1", "arg2");
expect(fn).toHaveBeenCalled(); expect(fn).toHaveBeenCalledTimes(1); expect(fn).toHaveBeenCalledWith("arg1", "arg2"); });
jest.fn() Compatibility
import { test, expect, jest } from "bun:test";
const fn = jest.fn(() => "value");
test("jest.fn works", () => { const result = fn(); expect(result).toBe("value"); expect(fn).toHaveBeenCalled(); });
Mock Return Values
const fn = mock();
// Return value once fn.mockReturnValueOnce("first"); fn.mockReturnValueOnce("second");
// Permanent return value fn.mockReturnValue("default");
// Promise returns fn.mockResolvedValue("resolved"); fn.mockResolvedValueOnce("once"); fn.mockRejectedValue(new Error("fail")); fn.mockRejectedValueOnce(new Error("once"));
Mock Implementations
const fn = mock();
// Set implementation fn.mockImplementation((x) => x * 2);
// One-time implementation fn.mockImplementationOnce((x) => x * 10);
// Chain implementations fn .mockImplementationOnce(() => "first") .mockImplementationOnce(() => "second") .mockImplementation(() => "default");
Spy on Methods
import { test, expect, spyOn } from "bun:test";
const obj = { method: () => "original", };
test("spy on method", () => { const spy = spyOn(obj, "method");
obj.method();
expect(spy).toHaveBeenCalled(); expect(obj.method()).toBe("original"); // Still works
// Override implementation spy.mockImplementation(() => "mocked"); expect(obj.method()).toBe("mocked");
// Restore spy.mockRestore(); expect(obj.method()).toBe("original"); });
Mock Modules
import { test, expect, mock } from "bun:test";
// Mock entire module mock.module("./utils", () => ({ add: mock(() => 999), subtract: mock(() => 0), }));
// Now imports use mocked version import { add } from "./utils";
test("mocked module", () => { expect(add(1, 2)).toBe(999); });
Mock Node Modules
mock.module("axios", () => ({ default: { get: mock(() => Promise.resolve({ data: "mocked" })), post: mock(() => Promise.resolve({ data: "created" })), }, }));
Mock with Factory
mock.module("./config", () => { return { API_URL: "http://test.local", DEBUG: true, }; });
Mock Assertions
const fn = mock();
fn("a", "b"); fn("c", "d");
// Call count expect(fn).toHaveBeenCalled(); expect(fn).toHaveBeenCalledTimes(2);
// Call arguments expect(fn).toHaveBeenCalledWith("a", "b"); expect(fn).toHaveBeenLastCalledWith("c", "d"); expect(fn).toHaveBeenNthCalledWith(1, "a", "b");
// Return values fn.mockReturnValue("result"); fn(); expect(fn).toHaveReturned(); expect(fn).toHaveReturnedWith("result"); expect(fn).toHaveReturnedTimes(1);
Mock Properties
const fn = mock(() => "value");
fn("arg1"); fn("arg2");
// Access call info fn.mock.calls; // [["arg1"], ["arg2"]] fn.mock.results; // [{ type: "return", value: "value" }, ...] fn.mock.lastCall; // ["arg2"]
// Clear history fn.mockClear(); // Clear calls, keep implementation fn.mockReset(); // Clear calls + implementation fn.mockRestore(); // Restore original (for spies)
Common Patterns
Mock Fetch
import { test, expect, spyOn } from "bun:test";
test("mock fetch", async () => { const spy = spyOn(global, "fetch").mockResolvedValue( new Response(JSON.stringify({ data: "mocked" })) );
const response = await fetch("/api/data"); const json = await response.json();
expect(json.data).toBe("mocked"); expect(spy).toHaveBeenCalledWith("/api/data");
spy.mockRestore(); });
Mock Console
test("mock console", () => { const spy = spyOn(console, "log");
console.log("test message");
expect(spy).toHaveBeenCalledWith("test message"); spy.mockRestore(); });
Mock Class Methods
class UserService { async getUser(id: string) { // Real implementation } }
test("mock class method", () => { const service = new UserService(); const spy = spyOn(service, "getUser").mockResolvedValue({ id: "1", name: "Test User", });
const user = await service.getUser("1");
expect(user.name).toBe("Test User"); expect(spy).toHaveBeenCalledWith("1"); });
Common Errors
Error Cause Fix
Cannot spy on undefined
Property doesn't exist Check property name
Not a function
Trying to mock non-function Use correct mock approach
Already mocked
Double mocking Use mockRestore first
Module not found
Wrong module path Check path in mock.module
When to Load References
Load references/mock-api.md when:
-
Complete mock/spy API reference
-
Advanced mocking patterns
Load references/module-mocking.md when:
-
Complex module mocking
-
Hoisting behavior details