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.
npx skills add secondsky/claude-skills --skill bun-test-mocking -a claude-codeWhat 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
axiosmodule and returns mock data - Create a spy on the
getUserclass method and verify call arguments - Mock global
fetchin 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-code2Manually: put the files in place
~/.claude/skills/bun-test-mocking/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/bun-test-mocking/
1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill bun-test-mocking -a codex2Manually: put the files in place
.agents/skills/bun-test-mocking/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill bun-test-mocking -a cursor2Manually: put the files in place
.cursor/skills/bun-test-mocking/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install secondsky/claude-skills bun-test-mocking2Manually: put the files in place
.github/skills/bun-test-mocking/SKILL.md1Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill bun-test-mocking -a gemini-cli2Platform CLI
gemini skills install https://github.com/secondsky/claude-skills --path plugins/bun/skills/bun-test-mockingManually: put the files in place
.devin/skills/bun-test-mocking/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add secondsky/claude-skills --skill bun-test-mocking -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
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