Documentation Index
Fetch the complete documentation index at: https://mintlify.com/zhcndoc/bun/llms.txt
Use this file to discover all available pages before exploring further.
Bun provides a Jest-compatible mocking API. You can mock functions, spy on objects, and mock entire modules.
Mock functions
Create a mock function with mock():
import { test, expect, mock } from "bun:test";
test("mock function", () => {
const mockFn = mock(() => "mocked");
const result = mockFn();
expect(result).toBe("mocked");
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(1);
});
Mock implementation
Control the return value of a mock:
import { test, expect, mock } from "bun:test";
test("mock implementation", () => {
const mockFn = mock((a: number, b: number) => a + b);
expect(mockFn(2, 3)).toBe(5);
expect(mockFn).toHaveBeenCalledWith(2, 3);
});
Mock return values
Set return values without providing a full implementation:
import { test, expect, mock } from "bun:test";
test("mock return value", () => {
const mockFn = mock();
mockFn.mockReturnValue(42);
expect(mockFn()).toBe(42);
expect(mockFn()).toBe(42);
});
test("mock return value once", () => {
const mockFn = mock();
mockFn.mockReturnValueOnce(1).mockReturnValueOnce(2).mockReturnValue(3);
expect(mockFn()).toBe(1);
expect(mockFn()).toBe(2);
expect(mockFn()).toBe(3);
expect(mockFn()).toBe(3);
});
Mock resolved/rejected values
For async functions:
import { test, expect, mock } from "bun:test";
test("mock resolved value", async () => {
const mockFn = mock();
mockFn.mockResolvedValue("success");
const result = await mockFn();
expect(result).toBe("success");
});
test("mock rejected value", async () => {
const mockFn = mock();
mockFn.mockRejectedValue(new Error("failed"));
await expect(mockFn()).rejects.toThrow("failed");
});
Mock implementation once
Provide different implementations for sequential calls:
import { test, expect, mock } from "bun:test";
test("mock implementation once", () => {
const mockFn = mock();
mockFn
.mockImplementationOnce(() => "first")
.mockImplementationOnce(() => "second")
.mockImplementation(() => "default");
expect(mockFn()).toBe("first");
expect(mockFn()).toBe("second");
expect(mockFn()).toBe("default");
expect(mockFn()).toBe("default");
});
Spying on objects
Use spyOn() to spy on methods of an object:
import { test, expect, spyOn } from "bun:test";
test("spy on method", () => {
const obj = {
method: () => "original"
};
const spy = spyOn(obj, "method");
obj.method();
expect(spy).toHaveBeenCalled();
expect(obj.method()).toBe("original"); // Original implementation preserved
});
Mock implementation
Override the implementation:
import { test, expect, spyOn } from "bun:test";
test("spy with mock implementation", () => {
const obj = {
getValue: () => "original"
};
const spy = spyOn(obj, "getValue").mockImplementation(() => "mocked");
expect(obj.getValue()).toBe("mocked");
expect(spy).toHaveBeenCalled();
});
Restore original implementation
Restore the original implementation:
import { test, expect, spyOn } from "bun:test";
test("restore spy", () => {
const obj = {
method: () => "original"
};
const spy = spyOn(obj, "method").mockReturnValue("mocked");
expect(obj.method()).toBe("mocked");
spy.mockRestore();
expect(obj.method()).toBe("original");
});
Automatic cleanup with using
Bun supports automatic cleanup with the using keyword:
import { test, expect, spyOn } from "bun:test";
test("auto-restore with using", () => {
const obj = {
method: () => "original"
};
{
using spy = spyOn(obj, "method").mockReturnValue("mocked");
expect(obj.method()).toBe("mocked");
} // spy.mockRestore() called automatically
expect(obj.method()).toBe("original");
});
Mock matchers
Check how mock functions were called:
import { test, expect, mock } from "bun:test";
test("mock matchers", () => {
const mockFn = mock();
mockFn("hello", 42);
mockFn("world", 100);
// Called at all
expect(mockFn).toHaveBeenCalled();
// Called specific number of times
expect(mockFn).toHaveBeenCalledTimes(2);
// Called with specific arguments
expect(mockFn).toHaveBeenCalledWith("hello", 42);
expect(mockFn).toHaveBeenLastCalledWith("world", 100);
expect(mockFn).toHaveBeenNthCalledWith(1, "hello", 42);
expect(mockFn).toHaveBeenNthCalledWith(2, "world", 100);
});
Mock properties
Access mock call history:
import { test, expect, mock } from "bun:test";
test("mock properties", () => {
const mockFn = mock((x: number) => x * 2);
mockFn(5);
mockFn(10);
// Access call history
expect(mockFn.mock.calls).toEqual([[5], [10]]);
expect(mockFn.mock.results).toEqual([
{ type: "return", value: 10 },
{ type: "return", value: 20 }
]);
// Call count
expect(mockFn.mock.calls.length).toBe(2);
});
Clearing and resetting mocks
mockClear()
Clears call history but preserves mock implementation:
import { test, expect, mock } from "bun:test";
test("clear mock", () => {
const mockFn = mock(() => "mocked");
mockFn();
expect(mockFn).toHaveBeenCalledTimes(1);
mockFn.mockClear();
expect(mockFn).toHaveBeenCalledTimes(0);
expect(mockFn()).toBe("mocked"); // Implementation preserved
});
mockReset()
Clears call history and removes mock implementation:
import { test, expect, mock } from "bun:test";
test("reset mock", () => {
const mockFn = mock(() => "mocked");
mockFn();
mockFn.mockReset();
expect(mockFn).toHaveBeenCalledTimes(0);
expect(mockFn()).toBeUndefined(); // Returns undefined
});
mockRestore()
Restores original implementation (for spies):
import { test, expect, spyOn } from "bun:test";
test("restore mock", () => {
const obj = { method: () => "original" };
const spy = spyOn(obj, "method").mockReturnValue("mocked");
expect(obj.method()).toBe("mocked");
spy.mockRestore();
expect(obj.method()).toBe("original");
});
Module mocking
Mock entire modules with mock.module():
import { test, expect, mock } from "bun:test";
mock.module("./math.ts", () => ({
add: mock((a: number, b: number) => 100), // Always returns 100
subtract: mock((a: number, b: number) => 0)
}));
test("mocked module", async () => {
const { add, subtract } = await import("./math.ts");
expect(add(2, 3)).toBe(100);
expect(subtract(5, 3)).toBe(0);
expect(add).toHaveBeenCalledWith(2, 3);
});
Partial module mocking
Mock specific exports while keeping others:
import { mock } from "bun:test";
mock.module("./utils.ts", () => {
const actual = require("./utils.ts");
return {
...actual,
dangerousFunction: mock(() => "safe")
};
});
Global mock utilities
jest.clearAllMocks()
Clears all mocks:
import { test, expect, mock } from "bun:test";
test("clear all mocks", () => {
const mock1 = mock();
const mock2 = mock();
mock1();
mock2();
jest.clearAllMocks();
expect(mock1).toHaveBeenCalledTimes(0);
expect(mock2).toHaveBeenCalledTimes(0);
});
jest.restoreAllMocks()
Restores all spies:
import { test, expect, spyOn } from "bun:test";
test("restore all mocks", () => {
const obj1 = { method: () => "original1" };
const obj2 = { method: () => "original2" };
spyOn(obj1, "method").mockReturnValue("mocked1");
spyOn(obj2, "method").mockReturnValue("mocked2");
jest.restoreAllMocks();
expect(obj1.method()).toBe("original1");
expect(obj2.method()).toBe("original2");
});