Jest-compatible testing framework with built-in mocking, fake timers, comprehensive expectation matchers, and seamless TypeScript integration optimized for fast test execution.
import { describe, test, it, expect, beforeAll, beforeEach, afterAll, afterEach } from "bun:test";
import { mock, spyOn, jest } from "bun:test";Structure and organize test suites with describe blocks and individual test cases.
/**
* Group related tests together
* @param name - Description of the test group
* @param fn - Function containing the tests
*/
function describe(name: string, fn: () => void): void;
/**
* Define an individual test case
* @param name - Test description
* @param fn - Test function
*/
function test(name: string, fn: () => void | Promise<void>): void;
/**
* Alias for test() - Jest compatibility
* @param name - Test description
* @param fn - Test function
*/
function it(name: string, fn: () => void | Promise<void>): void;
/** Skip a test group - won't be executed */
declare const describe.skip: typeof describe;
/** Run only this test group - others will be skipped */
declare const describe.only: typeof describe;
/** Mark test group as todo - will be reported but not executed */
declare const describe.todo: typeof describe;
/** Skip a test - won't be executed */
declare const test.skip: typeof test;
/** Run only this test - others will be skipped */
declare const test.only: typeof test;
/** Mark test as todo - will be reported but not executed */
declare const test.todo: typeof test;
/** Skip a test - won't be executed */
declare const it.skip: typeof it;
/** Run only this test - others will be skipped */
declare const it.only: typeof it;
/** Mark test as todo - will be reported but not executed */
declare const it.todo: typeof it;Usage Examples:
import { describe, test, expect } from "bun:test";
describe("Math operations", () => {
test("should add numbers correctly", () => {
expect(2 + 2).toBe(4);
});
test("should multiply numbers correctly", () => {
expect(3 * 4).toBe(12);
});
test.skip("this test is temporarily disabled", () => {
// This won't run
});
});
// Async tests
describe("Async operations", () => {
test("should handle promises", async () => {
const result = await Promise.resolve("success");
expect(result).toBe("success");
});
});Execute setup and teardown code before and after tests.
/**
* Run before all tests in the current describe block
* @param fn - Setup function
*/
function beforeAll(fn: () => void | Promise<void>): void;
/**
* Run before each test in the current describe block
* @param fn - Setup function
*/
function beforeEach(fn: () => void | Promise<void>): void;
/**
* Run after all tests in the current describe block
* @param fn - Cleanup function
*/
function afterAll(fn: () => void | Promise<void>): void;
/**
* Run after each test in the current describe block
* @param fn - Cleanup function
*/
function afterEach(fn: () => void | Promise<void>): void;Usage Examples:
import { describe, test, beforeEach, afterEach } from "bun:test";
describe("Database tests", () => {
let db: Database;
beforeAll(async () => {
// Setup shared resources
db = new Database(":memory:");
});
beforeEach(() => {
// Setup for each test
db.exec("DELETE FROM users");
});
afterEach(() => {
// Cleanup after each test
console.log("Test completed");
});
afterAll(() => {
// Cleanup shared resources
db.close();
});
test("should insert user", () => {
// Test implementation
});
});Comprehensive assertion library with Jest-compatible matchers and custom error messages.
/**
* Create an expectation for testing values
* @param actual - Value to test
* @returns Matchers object for assertions
*/
function expect<T>(actual: T): Matchers<T>;
interface Matchers<T> {
/** Strict equality check using Object.is() */
toBe(expected: T): void;
/** Deep equality check for objects and arrays */
toEqual(expected: T): void;
/** Check if value is strictly equal to true */
toBeTruthy(): void;
/** Check if value is strictly equal to false */
toBeFalsy(): void;
/** Check if value is null */
toBeNull(): void;
/** Check if value is undefined */
toBeUndefined(): void;
/** Check if value is defined (not undefined) */
toBeDefined(): void;
/** Check if value is NaN */
toBeNaN(): void;
/** Check if number is close to expected (for floating point) */
toBeCloseTo(expected: number, precision?: number): void;
/** Check if number is greater than expected */
toBeGreaterThan(expected: number): void;
/** Check if number is greater than or equal to expected */
toBeGreaterThanOrEqual(expected: number): void;
/** Check if number is less than expected */
toBeLessThan(expected: number): void;
/** Check if number is less than or equal to expected */
toBeLessThanOrEqual(expected: number): void;
/** Check if function throws an error */
toThrow(error?: string | RegExp | Error | ErrorConstructor): void;
/** Async version of toThrow for promises */
toThrowError(error?: string | RegExp | Error | ErrorConstructor): void;
/** Check if object has property */
toHaveProperty(propertyPath: string | string[], value?: any): void;
/** Check if array/string has specific length */
toHaveLength(length: number): void;
/** Check if string/array contains substring/element */
toContain(item: any): void;
/** Check if string matches regular expression */
toMatch(regexp: RegExp | string): void;
/** Check if array contains object matching properties */
toContainEqual(expected: any): void;
/** Check if mock function was called */
toHaveBeenCalled(): void;
/** Check if mock function was called specific number of times */
toHaveBeenCalledTimes(times: number): void;
/** Check if mock function was called with specific arguments */
toHaveBeenCalledWith(...args: any[]): void;
/** Check if mock function was last called with specific arguments */
toHaveBeenLastCalledWith(...args: any[]): void;
/** Check if mock function returned specific value */
toHaveReturnedWith(value: any): void;
/** Check if mock function returned (not threw) */
toHaveReturned(): void;
/** Check if mock function returned specific number of times */
toHaveReturnedTimes(times: number): void;
/** Negate the matcher */
not: Matchers<T>;
/** Add custom error message */
withContext(message: string): Matchers<T>;
}Usage Examples:
import { test, expect } from "bun:test";
test("number comparisons", () => {
expect(2 + 2).toBe(4);
expect(0.1 + 0.2).toBeCloseTo(0.3);
expect(5).toBeGreaterThan(3);
expect(10).toBeLessThanOrEqual(10);
});
test("string matching", () => {
expect("hello world").toContain("world");
expect("test@example.com").toMatch(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
});
test("object testing", () => {
const user = { id: 1, name: "Alice", email: "alice@example.com" };
expect(user).toHaveProperty("name", "Alice");
expect(user).toEqual({ id: 1, name: "Alice", email: "alice@example.com" });
});
test("array testing", () => {
const numbers = [1, 2, 3, 4, 5];
expect(numbers).toHaveLength(5);
expect(numbers).toContain(3);
expect(numbers).toContainEqual(4);
});
test("error testing", () => {
expect(() => {
throw new Error("Something went wrong");
}).toThrow("Something went wrong");
expect(() => JSON.parse("invalid")).toThrow(SyntaxError);
});Comprehensive mocking system for functions, modules, and objects with call tracking and behavior control.
/**
* Create a mock function
* @param implementation - Optional implementation function
* @returns Mock function with tracking capabilities
*/
function mock<T extends (...args: any[]) => any>(implementation?: T): Mock<T>;
interface Mock<T extends (...args: any[]) => any> extends jest.MockedFunction<T> {
/** Mock implementation function */
mockImplementation(fn: T): Mock<T>;
/** Mock implementation for one call */
mockImplementationOnce(fn: T): Mock<T>;
/** Mock return value */
mockReturnValue(value: ReturnType<T>): Mock<T>;
/** Mock return value for one call */
mockReturnValueOnce(value: ReturnType<T>): Mock<T>;
/** Mock resolved promise value */
mockResolvedValue(value: Awaited<ReturnType<T>>): Mock<T>;
/** Mock resolved promise value for one call */
mockResolvedValueOnce(value: Awaited<ReturnType<T>>): Mock<T>;
/** Mock rejected promise */
mockRejectedValue(error: any): Mock<T>;
/** Mock rejected promise for one call */
mockRejectedValueOnce(error: any): Mock<T>;
/** Clear call history but keep implementation */
mockClear(): Mock<T>;
/** Reset implementation to undefined */
mockReset(): Mock<T>;
/** Restore original implementation */
mockRestore(): void;
/** All calls made to this mock */
mock: {
calls: Parameters<T>[];
results: Array<{ type: 'return' | 'throw'; value: any }>;
instances: any[];
contexts: any[];
invocationCallOrder: number[];
};
}
/**
* Spy on an existing method
* @param object - Object containing the method
* @param method - Method name to spy on
* @returns Spy that can be used to track calls and modify behavior
*/
function spyOn<T extends object, K extends keyof T>(
object: T,
method: K
): Mock<T[K] extends (...args: any[]) => any ? T[K] : never>;
/**
* Mock an entire module
* @param modulePath - Path to module to mock
* @param factory - Factory function that returns mock implementation
* @returns Mock module
*/
function mockModule(modulePath: string, factory: () => any): void;Usage Examples:
import { test, expect, mock, spyOn } from "bun:test";
test("mock functions", () => {
const mockFn = mock();
mockFn("arg1", "arg2");
mockFn("arg3");
expect(mockFn).toHaveBeenCalledTimes(2);
expect(mockFn).toHaveBeenCalledWith("arg1", "arg2");
expect(mockFn).toHaveBeenLastCalledWith("arg3");
});
test("mock with implementation", () => {
const add = mock((a: number, b: number) => a + b);
expect(add(2, 3)).toBe(5);
expect(add).toHaveBeenCalledWith(2, 3);
});
test("mock return values", () => {
const mockFn = mock();
mockFn.mockReturnValue(42);
mockFn.mockReturnValueOnce(100);
expect(mockFn()).toBe(100); // First call
expect(mockFn()).toBe(42); // Subsequent calls
});
test("spy on methods", () => {
const calculator = {
add: (a: number, b: number) => a + b,
multiply: (a: number, b: number) => a * b
};
const addSpy = spyOn(calculator, "add");
calculator.add(2, 3);
expect(addSpy).toHaveBeenCalledWith(2, 3);
addSpy.mockReturnValue(10);
expect(calculator.add(2, 3)).toBe(10);
addSpy.mockRestore();
expect(calculator.add(2, 3)).toBe(5); // Original behavior restored
});
// Module mocking
mockModule("fs", () => ({
readFileSync: mock(() => "mocked file content"),
writeFileSync: mock()
}));Control time and timers in tests for deterministic testing of time-dependent code.
/**
* Set the system time for tests
* @param time - Time to set (Date, timestamp, or ISO string)
*/
function setSystemTime(time?: Date | number | string): void;
/**
* Restore real system time
*/
function restoreSystemTime(): void;
/** Jest compatibility namespace for time control */
declare namespace jest {
/** Enable fake timers */
function useFakeTimers(): void;
/** Disable fake timers and use real timers */
function useRealTimers(): void;
/** Advance fake timers by specified time */
function advanceTimersByTime(msToRun: number): void;
/** Run all pending timers */
function runAllTimers(): void;
/** Run only currently pending timers */
function runOnlyPendingTimers(): void;
/** Set system time */
function setSystemTime(time: Date | number): void;
/** Get number of pending timers */
function getTimerCount(): number;
}Usage Examples:
import { test, expect, jest, setSystemTime } from "bun:test";
test("time-dependent functionality", () => {
jest.useFakeTimers();
const callback = mock();
setTimeout(callback, 1000);
expect(callback).not.toHaveBeenCalled();
jest.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalled();
jest.useRealTimers();
});
test("date-dependent functionality", () => {
const fixedDate = new Date("2023-01-01T00:00:00Z");
setSystemTime(fixedDate);
expect(new Date().getFullYear()).toBe(2023);
restoreSystemTime();
});Full Jest compatibility layer for easy migration and familiar APIs.
declare namespace jest {
/** Create a mock function */
function fn<T extends (...args: any[]) => any>(implementation?: T): Mock<T>;
/** Spy on object method */
function spyOn<T extends object, K extends keyof T>(object: T, method: K): Mock<T[K]>;
/** Clear all mocks */
function clearAllMocks(): void;
/** Reset all mocks */
function resetAllMocks(): void;
/** Restore all mocks */
function restoreAllMocks(): void;
/** Mock module */
function mock(moduleName: string, factory?: () => any): void;
/** Unmock module */
function unmock(moduleName: string): void;
/** Require actual module (bypass mocks) */
function requireActual<T = any>(moduleName: string): T;
/** Require mock module */
function requireMock<T = any>(moduleName: string): T;
}Usage Examples:
import { test, expect, jest } from "bun:test";
test("Jest compatibility", () => {
const mockFn = jest.fn((x: number) => x * 2);
expect(mockFn(5)).toBe(10);
expect(mockFn).toHaveBeenCalledWith(5);
jest.clearAllMocks();
expect(mockFn).not.toHaveBeenCalled();
});/** Test function signature */
type TestFunction = () => void | Promise<void>;
/** Setup/teardown function signature */
type HookFunction = () => void | Promise<void>;
/** Test result metadata */
interface TestResult {
name: string;
status: "pass" | "fail" | "skip" | "todo";
duration: number;
error?: Error;
}
/** Test suite metadata */
interface SuiteResult {
name: string;
tests: TestResult[];
suites: SuiteResult[];
}