@aryzing/bun-mock-fetch

中文文档
1.2.2发布于 2026/10/28MITTypeScriptES Module构建来源已验证近 30 天下载 9933

在 Bun 获取请求 .

中文使用文档
文档目录17 节
  1. 目录
  2. 安装
  3. API 密码
  4. mockFetch
  5. clearFetchMocks
  6. json
  7. setPassthrough
  8. setLogging
  9. 配置
  10. 请求匹配者
  11. 回应
  12. 实例
  13. 用自己的模拟测试
  14. 使用共享模拟器的测试
  15. 开发过程中的模拟网络呼叫
  16. 开发过程中调试 API 调用
  17. 代理真实反应

Bun Moc 获取

在 Bun 获取请求 。 适合测试和调试.

目录

安装

bun add @aryzing/bun-mock-fetch

API 密码

mockFetch

mockFetch(requestMatcher: RequestMatcher, response: Response | ResponseFn): void

注册一个模拟。 何时 fetch 调用,请求匹配 requestMatcher页:1 response 返回,而不是提出真正的网络请求。 每次通话都增加了一个新的模拟器. 如果多个模拟符合请求,则最近注册的模拟优先.

clearFetchMocks

clearFetchMocks(): void

删除所有已注册的模拟并恢复原始内置 fetch。清空模拟不会改变 通过 或者说 记录 设置.

json

json(data: unknown, init?: ResponseInit): Response

创建一个 Response 数据序列化为 JSON 和 Content-Type: application/json 设置。 可选 init 已转交 Response 构造器并可用于设置自定义状态代码或附加头.

import { json, mockFetch } from "@aryzing/bun-mock-fetch";

// 200 JSON response.
mockFetch(/example/, json({ message: "Hello, world!" }));

// 201 JSON response.
mockFetch(/example/, json({ id: 1 }, { status: 201 }));

// 422 JSON error response.
mockFetch(/example/, json({ error: "Invalid input" }, { status: 422 }));

setPassthrough

setPassthrough(value: boolean): void

控制不匹配任何模拟的请求是否转发给本地内置 fetch。默认启用。 设定为 false 以无与伦比的请求取代.

setLogging

setLogging(value: boolean): void

启用或禁用调试日志 。 默认禁用 .

配置

请求匹配者

import { mockFetch } from "@aryzing/bun-mock-fetch";

// Simple string matching.
mockFetch("https://example.com", new Response());

// Using minimatch.
mockFetch("https://example.com/foo/**", new Response());

// Using regex.
mockFetch(/example/, new Response());

// Using a matcher function.
mockFetch((input, init) => {
  // Check input examples.
  if (typeof input === "string") return input.includes("example");
  if (input instanceof URL) return input.host.includes("example");
  if (input instanceof Request) return input.url.includes("example");

  // Check init example.
  return init?.method === "POST";
}, new Response());

// Using a detailed matcher object. All properties are optional.
mockFetch(
  {
    // Must match this string, glob, or regex.
    url: "https://example.com",
    // Must match this method (case-insensitive).
    method: "POST",
    // Must include these headers (case-insensitive) and match their values.
    headers: {
      "Content-Type": "application/json",
    },
  },
  new Response(),
);

回应

import { json, mockFetch } from "@aryzing/bun-mock-fetch";

// Text response.
mockFetch(/example/, new Response("Hello, world!"));

// JSON response.
mockFetch(/example/, json({ message: "Hello, world!" }));

// Response function.
mockFetch(/example/, async ({ mockedRequest, input, init, nativeFetch }) => {
  console.log(mockedRequest); // The matched mock request config.
  console.log(input); // The 1st arg. to `fetch`.
  console.log(init); // The 2nd arg. to `fetch`.

  // Delayed response example, useful for spinners and timeouts.
  await Bun.sleep(1000);

  // Proxy the request or otherwise fetch data using the native built-in fetch.
  const quote = await nativeFetch("https://example.com/quote-of-the-day").then(
    (r) => r.text(),
  );

  // Configure response based on request.
  const name =
    (await (input instanceof Request ? input : new Request("", init)).text()) ||
    "guest";

  return new Response(`Hello ${name}! ${quote}`);
});

实例

用自己的模拟测试

import { clearFetchMocks, mockFetch } from "@aryzing/bun-mock-fetch";

afterEach(() => {
  clearFetchMocks();
});

test("first test", async () => {
  mockFetch("https://api.example.com/data", new Response("first"));
  expect(await exampleApiClient.getData()).toBe("first");
});

test("second test", async () => {
  mockFetch("https://api.example.com/data", new Response("second"));
  expect(await exampleApiClient.getData()).toBe("second");
});

使用共享模拟器的测试

import { clearFetchMocks, mockFetch } from "@aryzing/bun-mock-fetch";

beforeAll(() => {
  mockFetch("https://foo.example.com/data", new Response("foo"));
  mockFetch("https://bar.example.com/data", new Response("bar"));
});

afterAll(() => {
  clearFetchMocks();
});

test("first test", async () => {
  expect(await exampleFooClient()).toBe("foo");
});

test("second test", async () => {
  expect(await exampleFooClient()).toBe("foo");
  expect(await exampleBarClient()).toBe("bar");
});

test("third test", async () => {
  expect(await exampleBarClient()).toBe("bar");
});

开发过程中的模拟网络呼叫

import { sdk } from "@example/sdk";
import { json, mockFetch } from "@aryzing/bun-mock-fetch";

mockFetch("https://sdk.example.com/auth", json({ token: "abc...def" }));
mockFetch("https://sdk.example.com/shopping-cart", json({ items: mockItems }));

await sdk.init(); // E.g., internally calls `/auth`
const items = await sdk.getShoppingCart();
render(items); // E.g., a UI framework

开发过程中调试 API 调用

允许日志向控制台打印每个被截取的请求 。 通道还在,所以所有无与伦比的请求仍然正常地通向真正的网络.

import { setLogging } from "@aryzing/bun-mock-fetch";

setLogging(true);

// All fetch calls will now be logged to the console, e.g.:
// [@aryzing/bun-mock-fetch]: Mocked fetch called with path: https://api.example.com/data
// [@aryzing/bun-mock-fetch]: No matching mock found for request: https://api.example.com/data
// [@aryzing/bun-mock-fetch]: Using built-in fetch for request: https://api.example.com/data

截取特定终点并检查其请求而不影响他人:

import { json, mockFetch, setLogging } from "@aryzing/bun-mock-fetch";

setLogging(true);

mockFetch("https://api.example.com/flaky-endpoint", async ({ input, init }) => {
  console.log("request headers:", init?.headers);
  return json({ debug: true });
});

代理真实反应

使用 nativeFetch 将请求转发给真正的网络,并修改答复后再返回.

import { mockFetch } from "@aryzing/bun-mock-fetch";

// Inject a field into every response from an endpoint.
mockFetch(
  "https://api.example.com/users",
  async ({ input, init, nativeFetch }) => {
    const response = await nativeFetch(input, init);
    const data = await response.json();
    return Response.json({ ...data, injected: true });
  },
);

// Add an auth header to outgoing requests before forwarding.
mockFetch(
  "https://api.example.com/**",
  async ({ input, init, nativeFetch }) => {
    return nativeFetch(input, {
      ...init,
      headers: { ...init?.headers, Authorization: "Bearer token123" },
    });
  },
);

版本与发布记录

@aryzing/bun-mock-fetch 共发布 14 个版本,首次发布于 2024/09/06;过去 12 个月发布了 4 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.2.2latest2026/10/2810 天前
1.2.12026/10/2810 天前
1.2.02026/03/097 个月前
1.1.12026/03/088 个月前
1.1.02025/08/071.3 年前
1.0.42025/08/071.3 年前

关于 @aryzing/bun-mock-fetch 的常见问题

@aryzing/bun-mock-fetch 是什么?

在 Bun 获取请求 .

如何安装 @aryzing/bun-mock-fetch?

在项目目录运行 npm install @aryzing/bun-mock-fetch,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:typescript(^5.0.0 || ^6.0.0 || ^7.0.2)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@aryzing/bun-mock-fetch 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@aryzing/bun-mock-fetch 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@aryzing/bun-mock-fetch 可以商用吗?

@aryzing/bun-mock-fetch 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@aryzing/bun-mock-fetch 的下载量有多少?

根据 npm 官方下载统计,@aryzing/bun-mock-fetch 在 2026/10/07 – 2026/11/05 这 30 天内被下载 9,933 次,日均约 331 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aryzing/bun-mock-fetch 还在维护吗?

最新版本 1.2.2 发布于 2026/10/28(10 天前);至今共发布 14 个版本,其中过去 12 个月发布了 4 个;首次发布于 2024/09/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。