new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Bun · Test runner · all subjects

mocking

26 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Create a mock function with mock()

Import `mock` from `bun:test` and pass a function to create a mock. The mock replaces the function with a controlled implementation that tracks calls and results. Example: `const random = mock(() => Math.random());`

jest.fn() behaves identically to mock()

Bun supports `jest.fn()` for compatibility with Jest. It behaves identically to the `mock()` function and can be used interchangeably.

Mock function properties and methods

Mock functions returned by `mock()` have these properties and methods: | Property/Method | Description | |---|---| | `mockFn.getMockName()` | Returns the mock name | | `mockFn.mock.calls` | Array of call arguments for each invocation | | `mockFn.mock.results` | Array of return values for each invocation | | `mockFn.mock.instances` | Array of instances created with `new` | | `mockFn.mock.contexts` | Array of `this` contexts for each invocation | | `mockFn.mock.lastCall` | Arguments of the most recent call | | `mockFn.mockClear()` | Clears call history | | `mockFn.mockReset()` | Clears call history and removes implementation | | `mockFn.mockRestore()` | Restores original implementation | | `mockFn.mockImplementation(fn)` | Sets a new implementation | | `mockFn.mockImplementationOnce(fn)` | Sets implementation for next call only | | `mockFn.mockName(name)` | Sets the mock name | | `mockFn.mockReturnThis()` | Sets the return value to `this` | | `mockFn.mockReturnValue(value)` | Sets a return value | | `mockFn.mockReturnValueOnce(value)` | Sets return value for next call only | | `mockFn.mockResolvedValue(value)` | Sets a resolved Promise value | | `mockFn.mockResolvedValueOnce(value)` | Sets resolved Promise for next call only | | `mockFn.mockRejectedValue(value)` | Sets a rejected Promise value | | `mockFn.mockRejectedValueOnce(value)` | Sets rejected Promise for next call only | | `mockFn.withImplementation(fn, callback)` | Temporarily changes implementation |

Use spyOn() to spy without replacing

The `spyOn()` function tracks calls to a function without replacing it with a mock. It preserves the original implementation while allowing call verification. Import from `bun:test`. Syntax: `spyOn(object, 'methodName')`

Spy on service methods example

This example demonstrates spying on methods to verify they are called correctly while preserving original implementation: ```ts import { test, expect, spyOn, afterEach } from "bun:test"; class UserService { async getUser(id: string) { return { id, name: `User ${id}` }; } async saveUser(user: any) { return { ...user, saved: true }; } } const userService = new UserService(); afterEach(() => { jest.restoreAllMocks(); }); test("spy on service methods", async () => { const getUserSpy = spyOn(userService, "getUser"); const saveUserSpy = spyOn(userService, "saveUser"); const user = await userService.getUser("123"); await userService.saveUser(user); expect(getUserSpy).toHaveBeenCalledWith("123"); expect(saveUserSpy).toHaveBeenCalledWith(user); }); test("spy with mock implementation", async () => { const getUserSpy = spyOn(userService, "getUser").mockResolvedValue({ id: "123", name: "Mocked User", }); const result = await userService.getUser("123"); expect(result.name).toBe("Mocked User"); expect(getUserSpy).toHaveBeenCalledWith("123"); }); ```

mock.module() to override a module

Use `mock.module(path: string, callback: () => Object)` to override the behavior of a module. The callback function returns an object with the mocked exports. Supports both ESM `import` and CommonJS `require`.

mock.module() basic example

This example shows how to mock a module: ```ts import { test, expect, mock } from "bun:test"; mock.module("./module", () => { return { foo: "bar", }; }); test("mock.module", async () => { const esm = await import("./module"); expect(esm.foo).toBe("bar"); const cjs = require("./module"); expect(cjs.foo).toBe("bar"); }); ```

mock.module() updates live bindings

Calling `mock.module()` overrides the module even if it has already been imported. Live bindings are updated, so previously imported references reflect the new mocked values for both ESM and CommonJS.

Use --preload to mock before imports

To ensure a module is mocked before it is imported, preventing the original module from being evaluated and its side effects from running, use the `--preload` flag when running tests: `bun test --preload ./my-preload`. To avoid typing this every time, add it to `bunfig.toml` under `[test]` section as `preload = ["./my-preload"]`.

mock.clearAllMocks() resets call history only

`mock.clearAllMocks()` resets the `.mock.calls`, `.mock.instances`, `.mock.contexts`, and `.mock.results` properties of every mock. Unlike `mock.restore()`, it does not restore the original implementation. The mock implementations set by `mockImplementation()`, `mockReturnValue()`, etc. are preserved.

jest.resetAllMocks() drops implementations

`jest.resetAllMocks()` (alias `vi.resetAllMocks()`) calls `mockFn.mockReset()` on every mock. In addition to clearing call history like `clearAllMocks()` does, it also drops the implementations set by `mockImplementation()`, `mockReturnValue()`, and similar methods. It does not restore the original implementation of a spy.

mock.restore() restores all mocks

`mock.restore()` restores every mock at once instead of calling `mockFn.mockRestore()` individually. It restores the original implementations of function mocks and spies. It does not reset modules overridden with `mock.module()`. Call it in an `afterEach` block or in a preload script to avoid repeating cleanup in every test.

mock.restore() example with spies

This example demonstrates restoring all spies at once: ```ts import { expect, mock, spyOn, test } from "bun:test"; import * as fooModule from "./foo.ts"; import * as barModule from "./bar.ts"; import * as bazModule from "./baz.ts"; test("foo, bar, baz", () => { const fooSpy = spyOn(fooModule, "foo"); const barSpy = spyOn(barModule, "bar"); const bazSpy = spyOn(bazModule, "baz"); // Original implementations still work expect(fooModule.foo()).toBe("foo"); expect(barModule.bar()).toBe("bar"); expect(bazModule.baz()).toBe("baz"); // Mock implementations fooSpy.mockImplementation(() => 42); barSpy.mockImplementation(() => 43); bazSpy.mockImplementation(() => 44); expect(fooModule.foo()).toBe(42); expect(barModule.bar()).toBe(43); expect(bazModule.baz()).toBe(44); // Restore all mock.restore(); expect(fooModule.foo()).toBe("foo"); expect(barModule.bar()).toBe("bar"); expect(bazModule.baz()).toBe("baz"); }); ```

Vitest compatibility with vi object

For compatibility with tests written for Vitest, Bun provides the `vi` object as an alias for parts of the Jest mocking API. Available functions on `vi`: `vi.fn`, `vi.spyOn`, `vi.mock`, `vi.restoreAllMocks`, `vi.resetAllMocks`, `vi.clearAllMocks`. This allows porting Vitest tests without rewriting mocks.

Module mock path resolution

When mocking a module with `mock.module()`, Bun resolves the module specifier the same way it resolves an `import`, supporting relative paths (`'./module'`), absolute paths (`'/path/to/module'`), and package names (`'lodash'`).

Mock factory callback lazy evaluation

The mock factory callback passed to `mock.module()` is only evaluated when the module is imported or required, not when `mock.module()` is called.

Mocked ESM modules maintain live bindings

Mocked ESM modules maintain live bindings, so changing the mock updates all existing imports of that module.

Module mocks with ESM and CommonJS

Module mocks interact with both ESM and CommonJS module caches. For ES modules, Bun patches JavaScriptCore so it can override export values at runtime and update live bindings recursively.

Bun does not support auto-mocking

Bun does not support the `__mocks__` directory or auto-mocking pattern used in Jest. Mocks must be explicitly created with `mock()`, `spyOn()`, or `mock.module()`.

API client mock module example

This example shows mocking an API client module with multiple mock functions: ```ts import { test, expect, mock, beforeEach } from "bun:test"; mock.module("./api-client", () => ({ fetchUser: mock(async (id: string) => ({ id, name: `User ${id}` })), createUser: mock(async (user: any) => ({ ...user, id: "new-id" })), updateUser: mock(async (id: string, user: any) => ({ ...user, id })), })); test("user service with mocked API", async () => { const { fetchUser } = await import("./api-client"); const { UserService } = await import("./user-service"); const userService = new UserService(); const user = await userService.getUser("123"); expect(fetchUser).toHaveBeenCalledWith("123"); expect(user.name).toBe("User 123"); }); ```

Mock external dependencies example

This example shows mocking an external database library: ```ts import { test, expect, mock } from "bun:test"; mock.module("pg", () => ({ Client: mock(function () { return { connect: mock(async () => {}), query: mock(async (sql: string) => ({ rows: [{ id: 1, name: "Test User" }], })), end: mock(async () => {}), }; }), })); test("database operations", async () => { const { Database } = await import("./database"); const db = new Database(); const users = await db.getUsers(); expect(users).toHaveLength(1); expect(users[0].name).toBe("Test User"); }); ```

Basic mock function example

This example demonstrates basic mock function usage with call verification: ```ts import { test, expect, mock } from "bun:test"; test("mock function behavior", () => { const mockFn = mock((x: number) => x * 2); const result1 = mockFn(5); const result2 = mockFn(10); expect(mockFn).toHaveBeenCalledTimes(2); expect(mockFn).toHaveBeenCalledWith(5); expect(mockFn).toHaveBeenLastCalledWith(10); expect(result1).toBe(10); expect(result2).toBe(20); expect(mockFn.mock.calls).toEqual([[5], [10]]); expect(mockFn.mock.results).toEqual([ { type: "return", value: 10 }, { type: "return", value: 20 }, ]); }); ```

Dynamic mock implementations example

This example shows setting different implementations for successive calls: ```ts import { test, expect, mock } from "bun:test"; test("dynamic mock implementations", () => { const mockFn = mock(); mockFn.mockImplementationOnce(() => "first"); mockFn.mockImplementationOnce(() => "second"); mockFn.mockImplementation(() => "default"); expect(mockFn()).toBe("first"); expect(mockFn()).toBe("second"); expect(mockFn()).toBe("default"); expect(mockFn()).toBe("default"); }); ```

Async mock functions example

This example demonstrates mocking async functions with resolved and rejected values: ```ts import { test, expect, mock } from "bun:test"; test("async mock functions", async () => { const asyncMock = mock(); asyncMock.mockResolvedValueOnce("first result"); asyncMock.mockResolvedValue("default result"); expect(await asyncMock()).toBe("first result"); expect(await asyncMock()).toBe("default result"); const rejectMock = mock(); rejectMock.mockRejectedValue(new Error("Mock error")); await expect(rejectMock()).rejects.toThrow("Mock error"); }); ```

clear all mocks example

This example shows `mock.clearAllMocks()` resetting call history while preserving implementations: ```ts import { expect, mock, test } from "bun:test"; const random1 = mock(() => Math.random()); const random2 = mock(() => Math.random()); test("clearing all mocks", () => { random1(); random2(); expect(random1).toHaveBeenCalledTimes(1); expect(random2).toHaveBeenCalledTimes(1); mock.clearAllMocks(); expect(random1).toHaveBeenCalledTimes(0); expect(random2).toHaveBeenCalledTimes(0); expect(typeof random1()).toBe("number"); expect(typeof random2()).toBe("number"); }); ```

reset all mocks example

This example shows `jest.resetAllMocks()` clearing call history and removing implementations: ```ts import { expect, jest, test } from "bun:test"; const random = jest.fn(() => Math.random()); test("resetting all mocks", () => { random(); expect(random).toHaveBeenCalledTimes(1); jest.resetAllMocks(); expect(random).toHaveBeenCalledTimes(0); expect(random()).toBeUndefined(); }); ```

Give your agent this brain