Jest takes 10 seconds to start. Bun's test runner starts in milliseconds. And it is built right in — no install needed.
Quick Start
# No installation needed — bun has it built in
bun test
// math.test.ts
import { expect, test, describe, beforeEach, mock } from "bun:test";
describe("math", () => {
test("addition", () => {
expect(2 + 2).toBe(4);
});
test("multiplication", () => {
expect(3 * 7).toBe(21);
});
});
Jest-Compatible API
import { expect, test, describe, beforeEach, afterEach, beforeAll, afterAll } from "bun:test";
// All Jest matchers work
expect(value).toBe(expected);
expect(value).toEqual(expected);
expect(value).toBeTruthy();
expect(value).toContain(item);
expect(value).toThrow();
expect(value).toMatchSnapshot();
expect(value).toHaveBeenCalled();
expect(value).toHaveBeenCalledWith(args);
Mocking
import { mock, spyOn } from "bun:test";
// Mock a function
const mockFn = mock(() => 42);
mockFn();
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveReturnedWith(42);
// Spy on an object method
const obj = { method: () => "original" };
const spy = spyOn(obj, "method").mockReturnValue("mocked");
expect(obj.method()).toBe("mocked");
// Mock a module
mock.module("./api", () => ({
fetchUsers: () => Promise.resolve([{ id: 1, name: "Alice" }]),
}));
Async Testing
test("fetches data", async () => {
const response = await fetch("https://api.example.com/users");
const data = await response.json();
expect(data).toBeArray();
expect(data.length).toBeGreaterThan(0);
});
test("handles timeout", async () => {
const promise = new Promise((_, reject) => {
setTimeout(() => reject(new Error("timeout")), 100);
});
expect(promise).rejects.toThrow("timeout");
});
Snapshot Testing
test("user object snapshot", () => {
const user = createUser("Alice", 30);
expect(user).toMatchSnapshot();
});
test("inline snapshot", () => {
expect({ a: 1, b: 2 }).toMatchInlineSnapshot(`
{
"a": 1,
"b": 2,
}
`);
});
DOM Testing (with happy-dom)
// bunfig.toml
// [test]
// preload = ["happy-dom"]
test("renders component", () => {
document.body.innerHTML = '<div id="app"></div>';
const app = document.getElementById("app");
app!.innerHTML = "<h1>Hello</h1>";
expect(document.querySelector("h1")!.textContent).toBe("Hello");
});
CLI Options
# Run specific file
bun test auth.test.ts
# Run tests matching pattern
bun test --grep "should handle"
# Watch mode
bun test --watch
# Coverage
bun test --coverage
# Timeout
bun test --timeout 10000
# Bail on first failure
bun test --bail
Speed Comparison
Project: 500 test files, 3000 tests
Jest: 35 seconds
Vitest: 12 seconds
Bun Test: 3 seconds
Bun Test vs Jest vs Vitest
| Feature | Bun Test | Jest | Vitest |
|---|---|---|---|
| Speed | Fastest | Slow | Fast |
| Install | Built-in | npm install | npm install |
| TypeScript | Native | ts-jest | Native |
| ESM | Native | Experimental | Native |
| Snapshots | Yes | Yes | Yes |
| Mocking | Yes | Yes | Yes |
| Coverage | Yes | Istanbul | c8/Istanbul |
| Watch | Yes | Yes | Yes |
Testing your web scraping code? Check out my Apify actors — tested and production-ready scrapers. For custom solutions, email spinov001@gmail.com.
Top comments (0)