Skip to main content
skill CX Codex

bun-test-mocking — Claude Code skill: what it does, how to install

Provides patterns for mock functions and module stubs in bun:test. Helpful when writing unit tests that replace network requests.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add secondsky/claude-skills --skill bun-test-mocking -a claude-code
Open on GitHub

What bun-test-mocking does

The skill guides coding agents through Bun test doubles and assertion APIs. It includes patterns for mock(), method interception via spyOn(), and module replacement using mock.module(). It also covers the jest import compatibility layer provided by bun:test.

Examples demonstrate mocking global fetch, silencing console.log, and stubbing class methods. Calling spy twice without resetting leads to runtime errors, so code must run spy.mockRestore() to keep test suites clean. Agents get precise rules for checking call arguments, return values, and inspecting mock.calls.

What it helps with

  • stub HTTP requests by mocking global fetch
  • replace external npm packages and local modules with mock.module
  • track method invocations and arguments using spyOn
  • configure chained and one-time return values in test doubles

Example prompts for the agent

  • Write a Bun test that mocks the axios module and returns mock data
  • Create a spy on the getUser class method and verify call arguments
  • Mock global fetch in a Bun unit test and restore it after execution

How to install bun-test-mocking

1Skills CLI (Vercel)

npx skills add secondsky/claude-skills --skill bun-test-mocking -a claude-code

2Manually: put the files in place

~/.claude/skills/bun-test-mocking/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/bun-test-mocking/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about bun-test-mocking

How to install bun-test-mocking in Claude Code?

Run npx skills add secondsky/claude-skills --skill bun-test-mocking -a claude-code. This installs the skill file into your agent environment.

What does bun-test-mocking do?

It teaches the agent the exact mocking syntax of bun:test. This includes mock functions, spy lifecycle management, module factories, and call assertions.

Does bun-test-mocking support Jest syntax?

Yes. The skill explains how to import jest directly from bun:test so you can use jest.fn() without extra dependencies.

Source text

SKILL.md · MIT
---
name: bun-test-mocking
description: Use for mock functions in Bun tests, spyOn, mock.module, implementations, and test doubles.
metadata:
  version: "1.0.0"
license: MIT
---

# Bun Test Mocking

Bun provides Jest-compatible mocking with `mock()`, `spyOn()`, and module mocking.

## Mock Functions

```typescript
import { test, expect, mock } from "bun:test";

// Create mock function
const fn = mock(() => "original");

test("mock function", () => {
  fn("arg1", "arg2");

  expect(fn).toHaveBeenCalled();
  expect(fn).toHaveBeenCalledTimes(1);
  expect(fn).toHaveBeenCalledWith("arg1", "arg2");
});
```

### jest.fn() Compatibility

```typescript
import { test, expect, jest } from "bun:test";

const fn = jest.fn(() => "value");

test("jest.fn works", () => {
  const result = fn();
  expect(result).toBe("value");
  expect(fn).toHaveBeenCalled();
});
```

## Mock Return Values

```typescript
const fn = mock();

// Return value once
fn.mockReturnValueOnce("first");
fn.mockReturnValueOnce("second");

// Permanent return value
fn.mockReturnValue("default");

// Promise returns
fn.mockResolvedValue("resolved");
fn.mockResolvedValueOnce("once");
fn.mockRejectedValue(new Error("fail"));
fn.mockRejectedValueOnce(new Error("once"));
```

## Mock Implementations

```typescript
const fn = mock();

// Set implementation
fn.mockImplementation((x) => x * 2);

// One-time implementation
fn.mockImplementationOnce((x) => x * 10);

// Chain implementations
fn
  .mockImplementationOnce(() => "first")
  .mockImplementationOnce(() => "second")
  .mockImplementation(() => "default");
```

## Spy on Methods

```typescript
import { test, expect, spyOn } from "bun:test";

const obj = {
  method: () => "original",
};

test("spy on method", () => {
  const spy = spyOn(obj, "method");

  obj.method();

  expect(spy).toHaveBeenCalled();
  expect(obj.method()).toBe("original"); // Still works

  // Override implementation
  spy.mockImplementation(() => "mocked");
  expect(obj.method()).toBe("mocked");

  // Restore
  spy.mockRestore();
  expect(obj.method()).toBe("original");
});
```

## Mock Modules

```typescript
import { test, expect, mock } from "bun:test";

// Mock entire module
mock.module("./utils", () => ({
  add: mock(() => 999),
  subtract: mock(() => 0),
}));

// Now imports use mocked version
import { add } from "./utils";

test("mocked module", () => {
  expect(add(1, 2)).toBe(999);
});
```

### Mock Node Modules

```typescript
mock.module("axios", () => ({
  default: {
    get: mock(() => Promise.resolve({ data: "mocked" })),
    post: mock(() => Promise.resolve({ data: "created" })),
  },
}));
```

### Mock with Factory

```typescript
mock.module("./config", () => {
  return {
    API_URL: "http://test.local",
    DEBUG: true,
  };
});
```

## Mock Assertions

```typescript
const fn = mock();

fn("a", "b");
fn("c", "d");

// Call count
expect(fn).toHaveBeenCalled();
expect(fn).toHaveBeenCalledTimes(2);

// Call arguments
expect(fn).toHaveBeenCalledWith("a", "b");
expect(fn).toHaveBeenLastCalledWith("c", "d");
expect(fn).toHaveBeenNthCalledWith(1, "a", "b");

// Return values
fn.mockReturnValue("result");
fn();
expect(fn).toHaveReturned();
expect(fn).toHaveReturnedWith("result");
expect(fn).toHaveReturnedTimes(1);
```

## Mock Properties

```typescript
const fn = mock(() => "value");

fn("arg1");
fn("arg2");

// Access call info
fn.mock.calls;        // [["arg1"], ["arg2"]]
fn.mock.results;      // [{ type: "return", value: "value" }, ...]
fn.mock.lastCall;     // ["arg2"]

// Clear history
fn.mockClear();       // Clear calls, keep implementation
fn.mockReset();       // Clear calls + implementation
fn.mockRestore();     // Restore original (for spies)
```

## Common Patterns

### Mock Fetch

```typescript
import { test, expect, spyOn } from "bun:test";

test("mock fetch", async () => {
  const spy = spyOn(global, "fetch").mockResolvedValue(
    new Response(JSON.stringify({ data: "mocked" }))
  );

  const response = await fetch("/api/data");
  const json = await response.json();

  expect(json.data).toBe("mocked");
  expect(spy).toHaveBeenCalledWith("/api/data");

  spy.mockRestore();
});
```

### Mock Console

```typescript
test("mock console", () => {
  const spy = spyOn(console, "log");

  console.log("test message");

  expect(spy).toHaveBeenCalledWith("test message");
  spy.mockRestore();
});
```

### Mock Class Methods

```typescript
class UserService {
  async getUser(id: string) {
    // Real implementation
  }
}

test("mock class method", () => {
  const service = new UserService();
  const spy = spyOn(service, "getUser").mockResolvedValue({
    id: "1",
    name: "Test User",
  });

  const user = await service.getUser("1");

  expect(user.name).toBe("Test User");
  expect(spy).toHaveBeenCalledWith("1");
});
```

## Common Errors

| Error | Cause | Fix |
|-------|-------|-----|
| `Cannot spy on undefined` | Property doesn't exist | Check property name |
| `Not a function` | Trying to mock non-function | Use correct mock approach |
| `Already mocked` | Double mocking | Use mockRestore first |
| `Module not found` | Wrong module path | Check path in mock.module |

## When to Load References

Load `references/mock-api.md` when:
- Complete mock/spy API reference
- Advanced mocking patterns

Load `references/module-mocking.md` when:
- Complex module mocking
- Hoisting behavior details

© secondsky · MIT · secondsky/claude-skills

Similar skills

All skills for Testing and QA →

From the same set128

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor