bun.directory

Search bun.directory

Find a skill or the Node package you want to replace

GitHubSubmit

bun test

Queued

Use when writing, running or configuring tests in a Bun project. Use bun test and bun:test instead of jest, vitest, ts-jest, mocha, chai, sinon or nock.

bunx bun.directory add bun-test
View source
Verification lift

Queued. The verifier will run each of the 2 tasks with and without this skill, then score the lift.

2 tasks

SKILL.md

7 sections

Bun has a Jest-compatible test runner built in. It runs TypeScript and JSX directly, with no config, transpiler or preset. Don't install jest, vitest, ts-jest, babel-jest, mocha, chai or sinon.

Write a test

// src/slugify.test.ts — files named *.test.ts, *_test.ts, *.spec.ts (or .js/.tsx) are picked up.
import { describe, expect, test } from "bun:test";
import { slugify } from "./slugify";

describe("slugify", () => {
  test("lowercases and hyphenates", () => {
    expect(slugify("Hello World")).toBe("hello-world");
  });

  test.each([
    ["  padded  ", "padded"],
    ["Ünïcödé", "unicode"],
  ])("%p → %p", (input, output) => {
    expect(slugify(input)).toBe(output);
  });
});

Import from "bun:test". The globals also work without an import, but explicit imports keep bun check happy without extra types config.

Run

bun test                       # every test file under the cwd
bun test src/slugify           # filter by path substring
bun test -t "hyphenates"       # filter by test name
bun test --watch               # rerun on change
bun test --coverage            # coverage table (add --coverage-reporter=lcov for CI)
bun test --bail                # stop at the first failure

In package.json: "test": "bun test". Configure defaults (coverage, preload, timeout) under [test] in bunfig.toml, not in a jest config file.

Matchers

toBe, toEqual, toStrictEqual, toMatchObject, toContain, toHaveLength, toThrow, toBeNull, toBeDefined, toBeCloseTo, resolves/rejects, toMatchSnapshot, toMatchInlineSnapshot, expect.any(Number), expect.objectContaining(...), and expect.assertions(n) all work as in Jest.

Mocks and spies

import { mock, spyOn, afterEach } from "bun:test";

const send = mock((to: string) => true);
send("a@b.c");
expect(send).toHaveBeenCalledWith("a@b.c");

const spy = spyOn(console, "error").mockImplementation(() => {});
afterEach(() => mock.restore()); // restores every spyOn

// Replace a module for everything that imports it after this call.
mock.module("./db", () => ({ getUser: () => ({ id: 1, name: "Test" }) }));

Mock fetch

Assign a mock to globalThis.fetch. No nock, msw or jest-fetch-mock.

const realFetch = globalThis.fetch;
afterEach(() => {
  globalThis.fetch = realFetch;
});

test("parses the API", async () => {
  globalThis.fetch = mock(async () =>
    Response.json({ temp: 21 }),
  ) as unknown as typeof fetch;
  expect(await getTemp("London")).toBe(21);
});

Control time

import { setSystemTime, jest } from "bun:test";

setSystemTime(new Date("2026-01-01T00:00:00Z")); // Date.now() and new Date() are frozen
setSystemTime(); // back to the real clock

jest.useFakeTimers(); // setTimeout/setInterval
jest.advanceTimersByTime(1000);
jest.useRealTimers();

Lifecycle and structure

  • beforeAll, beforeEach, afterEach, afterAll work per file or per describe.
  • --preload ./test/setup.ts (or preload in bunfig.toml [test]) runs setup before every file.
  • test.skip, test.todo, test.only (with --only), test.if(cond), and test.failing exist.
  • Default timeout is 5s per test. Pass a third argument (test("slow", fn, 30_000)) or --timeout.
  • Tests in a file run serially; files run in one process. Use test.concurrent for independent async tests.

Testing servers

Start Bun.serve({ port: 0, ... }) in beforeAll, call it with fetch(new URL(path, server.url)), and server.stop() in afterAll. Don't use supertest.

Don't

  • Don't install jest, vitest, ts-jest, @types/jest, babel-jest, mocha, chai, sinon, nock, supertest or jest-fetch-mock.
  • Don't add a jest.config.* or vitest.config.* file.
  • Don't import from @jest/globals or vitest; import from bun:test.

How the verifier tests it

01
mock-fetch-and-timeWrite tests for src/weather.ts. The tests must not make real network requests and must not depend on the current date or time. Test that getForecast builds the right URL, parses the response, labels the reading "stale" when it is more than an hour old and "fresh" otherwise, and throws a helpful error when the API returns a non-2xx status. Add a `test` script in package.json.
02
slugify-testsAdd a test suite for src/slugify.ts and a `test` script in package.json so `bun run test` runs it. Cover lowercasing, collapsing whitespace and punctuation to single hyphens, trimming leading and trailing hyphens, stripping accents, and the empty string. Write at least five tests.
Requires
Bun >=1.2.0
Tasks
2
Author
bgribbin

Other ways to install

bunx bun.directory add bun-test