agentsclimarketplace

Bun test mocking

Skill secondsky/claude-skills/plugins/bun/skills/bun-test-mocking

Production-ready skills for Claude Code CLI - Cloudflare, React, Tailwind v4, and AI integrations

Install
npx -y skills add secondsky/claude-skills --skill bun-test-mocking

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Use for mock functions in Bun tests, spyOn, mock.module, implementations, and test doubles.

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

5.2 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it

Bun Test Mocking

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

Mock Functions

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

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

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

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

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

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

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

Mock with Factory

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

Mock Assertions

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

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

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

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

  console.log("test message");

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

Mock Class Methods

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

ErrorCauseFix
Cannot spy on undefinedProperty doesn't existCheck property name
Not a functionTrying to mock non-functionUse correct mock approach
Already mockedDouble mockingUse mockRestore first
Module not foundWrong module pathCheck 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

Gives 0 of the 12 instructions most test skills give in ~1.3k tokens

Counted across 964 of the 1,571 authors here whose files we hold, read 2026-08-06

  • close the browser when donein 55 of 964, across 12 files
  • wait for network idle statein 51 of 964, across 6 files
  • launch chromium in headless modein 49 of 964, across 6 files
  • use descriptive selectors for elementsin 49 of 964, across 6 files
  • run provided scripts with help flag firstin 49 of 964, across 6 files
  • add appropriate explicit waitsin 48 of 964, across 5 files
  • use bundled scripts as black boxesin 46 of 964, across 3 files
  • do not read script source codein 46 of 964, across 3 files
  • use sync playwright for scriptsin 46 of 964, across 3 files
  • inspect dom before executing actionsin 46 of 964, across 3 files
  • run the full test suitein 36 of 964, across 34 files
  • write the failing test firstin 25 of 964, across 18 files

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.