比较

Mock Service Worker 与类似工具的比较。

为工作选择正确的工具至关重要。我们尽力在下面提供 Mock Service Worker 和其他开源 API 模拟库之间的全面和公正的比较。

¥Choosing the right tool for the job is crucial. We tried our best to provide a comprehensive and unbiased comparison between Mock Service Worker and other open-source API mocking libraries below.

比较标准

¥Comparison criteria

任何好的比较都始于一组明确定义的标准。以下是我们在比较 MSW 和其他替代方案时使用的标准(从开发者的角度编写):

¥Any good comparison begins with a clearly defined set of criteria. Here are the criteria we used when comparing MSW to alternatives (written from a developer’s perspective):

  • 支持的 API 类型。我可以用库模拟哪些类型的 API?

    ¥Supported API types. What kinds of API can I mock with the library?

  • 环境。我在哪些环境中可以使用该库?

    ¥Environment. In which environments can I use the library?

  • 实现。库如何实现请求拦截?

    ¥Implementation. How does the library implement request interception?

  • 集成。将它集成到我的项目中需要多少努力?

    ¥Integration. How much effort it takes to integrate it into my project?

  • 定义。我如何定义模拟?

    ¥Definition. How do I define mocks?

Nock

Nock 是一个用于 Node.js 的 HTTP 服务器模拟和期望库。

¥Nock is an HTTP server mocking and expectations library for Node.js.

Nock 是一个很棒的库,用于在 Node.js 中结合 API 模拟和断言。虽然 Mock Service Worker 没有内置断言功能,但它允许你在浏览器和 Node.js 之间无缝重用相同的模拟,并提供一流的 GraphQL 支持和基于标准的请求/响应处理。

¥Nock is a great library for combining API mocking and assertions in Node.js. While Mock Service Worker doesn’t come with a built-in assertion capabilities, it allows you to seamlessly reuse the same mocks across browser and Node.js, as well as providing first-class GraphQL support and standard-based request/response handling.

API 支持

¥API support

API 类型Nock模拟服务工作者
REST API
GraphQL API
WebSocket API

支持的环境

¥Supported environment

环境Nock模拟服务工作者
Node.js
浏览器

集成

¥Integration

Nock模拟服务工作者
不需要对代码进行任何更改。不需要对代码进行任何更改。
需要额外的适配器来拦截特定的请求客户端(例如 axios适用于任何请求客户端,无需额外配置。

定义

¥Definition

Nock

Nock 使用方法链来拦截请求并声明模拟响应:

¥Nock uses method chaining to intercept requests and declare mocked responses:

nock('https://api.example.com').get('/user').reply(200, { id: 1, name: 'John' })

模拟服务工作者

¥Mock Service Worker

MSW 在服务器端路由之后对其拦截 API 进行建模,并根据 Fetch API 规范处理请求和响应,使用你在 JavaScript 中通常使用的相同类:

¥MSW models its interception API after server-side routing and handles requests and responses according to the Fetch API specification, using the same classes you would use normally in JavaScript:

http.get('https://api.example.com/user', async ({ request }) => {
  const payload = await request.json()
  return HttpResponse.json({ id: 1, name: 'John' })
})

JSON 服务器

¥JSON Server

JSON 服务器 允许你基于 JSON 文件创建实际的 HTTP 服务器。

¥JSON Server allows you to create an actual HTTP server based on a JSON file.

JSON 服务器是一个实际的 HTTP 服务器,它使用抽象响应定义格式。这意味着你必须运行和维护服务器。Mock Service Worker 不会生成任何服务器,因此其初始化成本是免费的。Mock Service Worker 还允许你使用 TypeScript 等语言并从实际后端实现中生成模拟,从而拥有更多防错模拟定义。

¥JSON Server is an actual HTTP server that utilizes abstract response definition format. This means a server you have to run and maintain. Mock Service Worker doesn’t spawn any servers, so its initialization cost is free. Mock Service Worker also allows you to have more error-proof mock definitions by using languages like TypeScript and generating mocks out of the actual backend implementation.

API 支持

¥API support

API 类型JSON 服务器模拟服务工作者
REST API
GraphQL API
WebSocket API

支持的环境

¥Supported environment

环境JSON 服务器模拟服务工作者
Node.js
浏览器✅ X1

1—JSON 服务器实际上并不在浏览器中运行。由于它是一个独立的服务器,因此可以从系统中的任何位置请求它。

¥1—JSON Server doesn’t actually run in the browser. Since it’s a standalone server, it can be requested from anywhere in your system.

集成

¥Integration

JSON 服务器模拟服务工作者
需要更改代码以从模拟服务器请求资源。不需要对代码进行任何更改。
适用于任何请求客户端,无需额外配置。适用于任何请求客户端,无需额外配置。

定义

¥Definition

JSON 服务器

¥JSON Server

JSON 服务器使用资源优先路由格式,隐式生成请求路径并描述模拟响应。

¥JSON Server uses a resource-first routes format that implicitly generates request paths and describes mocked responses.

{
  "posts": [
    { "id": 1, "title": "json-server" },
    { "id": 2, "title": "mock-service-worker" }
  ]
}

这将根据描述的资源自动生成服务器端路由,如 GET /postsDELETE /posts/:index。此类路由的性质是静态的,需要额外的抽象才能实现更复杂的网络行为。

¥This will automatically generate server-side routes like GET /posts and DELETE /posts/:index based on the described resources. The nature of such routes is static and requires additional abstractions to achieve more complex network behaviors.

模拟服务工作者

¥Mock Service Worker

MSW 在服务器端路由之后对其拦截 API 进行建模,并根据 Fetch API 规范处理请求和响应,使用你在 JavaScript 中通常使用的相同类:

¥MSW models its interception API after server-side routing and handles requests and responses according to the Fetch API specification, using the same classes you would use normally in JavaScript:

http.get('/posts', () => {
  return HttpResponse.json([
    { id: 1, title: 'json-server' },
    { id: 2, title: 'mock-service-worker' },
  ])
})

使用 MSW,你必须明确定义服务器端操作,如 http.get('/posts')http.delete('/posts/:index')。MSW 优先考虑显式性,利用编程请求解析,允许更复杂的网络行为。

¥With MSW, you have to explicitly define server-side operations like http.get('/posts') or http.delete('/posts/:index'). MSW prioritized explicitness, taking advantage of programmatic request resolution, allowing for more complex network behaviors.

Mirage

Mirage 是一个 API 模拟库,可让你构建、测试和共享完整的 JavaScript 应用,而无需依赖任何后端服务。

¥Mirage is an API mocking library that lets you build, test and share a complete working JavaScript application without having to rely on any backend services.

Mirage 以数据建模为中心,以模拟更复杂的服务器行为。Mock Service Worker 没有内置数据建模功能,而是在名为 @mswjs/data 的单独包中公开它们。这样,你可以在需要时将建模带到桌面上。

¥Mirage is centered around data modeling to emulate more complex server behaviors. Mock Service Worker doesn’t come with a built-in data modeling capabilities and instead exposes them in a separate package called @mswjs/data. This way you can bring modeling to the table once you need it.

API 支持

¥API support

API 类型Mirage模拟服务工作者
REST API
GraphQL API
WebSocket API

支持的环境 =

¥Supported environments

环境Mirage模拟服务工作者
Node.js
浏览器

实现

¥Implementation

环境Mirage模拟服务工作者
浏览器Monkey-patches fetchXMLHttpRequest(使用 pretender)。使用服务工作线程在浏览器级别拦截请求。

集成

¥Integration

Mirage模拟服务工作者
不需要对代码进行任何更改。不需要对代码进行任何更改。
适用于任何请求客户端,无需额外配置。适用于任何请求客户端,无需额外配置。

定义

¥Definition

Mirage

Mirage 使用路由处理程序格式来定义类似服务器的路由和模拟响应。

¥Mirage uses route handlers format to define server-like routes and mocked responses.

createServer({
  routes() {
    this.get('/movies', () => {
      return ['Interstellar', 'Inception', 'Dunkirk']
    })
  },
})

Mirage 还带有一个内存数据库,可帮助你建模更复杂的数据关系。

¥Mirage also comes with an in-memory database to help you model more complex data relationships.

createServer({
  models: {
    movie: Model.extend({
      castMembers: hasMany(),
    }),
    castMember: Model.extend({
      movie: belongsTo(),
    }),
  },
  routes() {
    // Your route handlers responding with the data.
  },
})

模拟服务工作者

¥Mock Service Worker

MSW 在服务器端路由之后对其拦截 API 进行建模,并根据 Fetch API 规范处理请求和响应,使用你在 JavaScript 中通常使用的相同类:

¥MSW models its interception API after server-side routing and handles requests and responses according to the Fetch API specification, using the same classes you would use normally in JavaScript:

http.get('/movies', () => {
  return HttpResponse.json(['Interstellar', 'Inception', 'Dunkirk'])
})

尽管 MSW 没有提供内置的数据建模功能,但它利用生态系统包(如 @mswjs/data)为你提供数据优先的 API 模拟方法(如果你选择的话)。

¥Although MSW doesn’t ship data modeling capabilities built-in, it leverages ecosystem packages, like @mswjs/data, to give you a data-first approach to API mocking if you choose it.

import { factory, primaryKey, oneOf, manyOf } from '@mswjs/data'
 
// Model the data.
const db = factory({
  movie: {
    id: primaryKey(randomUuid),
    title: String,
    castMembers: manyOf('castMember'),
  },
  castMember: {
    id: primaryKey(randomUuid),
    name: String,
    movie: oneOf('movie'),
  },
})
 
// Generate request handlers based on the models.
// - GET /movies
// - GET /movies/:id
// - POST /movies
// - ...
db.toHandlers('rest')
 
// Including GraphQL queries!
// - query ListMovies
// - query GetMovie
// - mutation AddMovie
// - ...
db.toHandlers('graphql')

Cypress - cy.intercept()

Cypress 是一个端到端测试框架,通过其 cy.intercept() API 提供 API 模拟功能。

¥Cypress is an end-to-end testing framework that provides API mocking capabilities through its cy.intercept() API.

API 支持

¥API support

API 类型cy.intercept()模拟服务工作者
REST API
GraphQL API❌ X1
WebSocket API

1—尽管可以通过自定义别名处理 GraphQL 请求,但仍需要大量额外设置。Cypress 通过 HTTP 处理实现 GraphQL API 模拟(因为 GraphQL 最常在 Web 上通过 HTTP 实现),而不是一流的 GraphQL 支持。

¥1—Although it is possible to work with GraphQL requests through custom aliasing, it still requires a lot of additional setup. Cypress achieves GraphQL API mocking through HTTP handling (since GraphQL is most commonly implemented over HTTP on the web) instead of a first-class GraphQL support.

支持的环境 =

¥Supported environments

API 类型cy.intercept()模拟服务工作者
Node.js❌ X1
浏览器

1—Cypress 是一个浏览器测试框架,这意味着你不能在 Node.js 进程中使用 cy.intercept() 模拟,例如集成测试或后端应用。

¥1—Cypress is a browser testing framework, which means you cannot use your cy.intercept() mocks in a Node.js process, like an integration test or a backend application.

实现

¥Implementation

环境cy.intercept()模拟服务工作者
浏览器使用浏览器范围的 HTTP 代理通过 Cypress 作为其运行时的一部分生成的自定义服务器路由传出请求。使用服务工作线程在浏览器级别拦截请求。

集成

¥Integration

cy.intercept()模拟服务工作者
不需要更改代码。Cypress 原生可用。不需要更改代码。
适用于任何请求客户端,无需额外配置。适用于任何请求客户端,无需额外配置。

定义

¥Definition

cy.intercept()

Cypress 使用自定义匹配器签名和路由处理程序函数来拦截和处理请求。它利用自定义方法(如 req.reply()req.continue()req.redirect())进行更详细的请求控制。

¥Cypress uses a custom matcher signature and a route handler function to intercept and handle requests. It utilizes custom methods like req.reply(), req.continue() or req.redirect() for more detailed request control.

cy.intercept('POST', '/users', {
  statusCode: 201,
  body: req.body,
  delay: 100,
})

模拟服务工作者

¥Mock Service Worker

MSW 在服务器端路由之后对其拦截 API 进行建模,并根据 Fetch API 规范处理请求和响应,使用你在 JavaScript 中通常使用的相同类:

¥MSW models its interception API after server-side routing and handles requests and responses according to the Fetch API specification, using the same classes you would use normally in JavaScript:

import { http, delay } from 'msw'
 
http.post('/users', async ({ request }) => {
  // Read the request body as you would normally.
  const user = await request.json()
 
  // Control the response resolver execution flow
  // via Promises, like this "delay" Promise below.
  await delay(100)
 
  // Construct a response as you would normally.
  return HttpResponse.json(user, { status: 201 })
})

MSW 通过其 passthrough()bypass() API 为你提供对请求的更高级控制,这些 API 仍然会在后台产生语义 HTTP 响应。

¥MSW gives you a more advanced control over the requests through its passthrough() and bypass() APIs, which still yield semantic HTTP responses under the hood.

Playwright - page.route()

Playwright 是一个浏览器测试工具,它通过其 page.route() API 提供 API 模拟功能。

¥Playwright is a browser testing tool that provides API mocking capabilities through its page.route() API.

API 支持

¥API support

API 类型page.route()模拟服务工作者
REST API
GraphQL API❌ X1
WebSocket API

1—你可以使用 page.route() 处理 GraphQL 请求,因为它们也是 HTTP 请求,但 Playwright 不提供对模拟 GraphQL API 的一流支持。

¥1—You can handle GraphQL requests with page.route() since they are also HTTP requests but Playwright does not provide a first-class support for mocking GraphQL APIs.

支持的环境 =

¥Supported environments

API 类型page.route()模拟服务工作者
Node.js❌ X1
浏览器

1—尽管使用 Playwright 你可以在 Node.js 中编写测试,但 Playwright 本身(及其 page.route())只会影响生成的浏览器中的流量,而不会影响 Node.js 进程。

¥1—Although with Playwright you write your tests in Node.js, Playwright itself (and its page.route()) only affect the traffic in the spawned browser, not the Node.js process.

实现

¥Implementation

环境page.route()模拟服务工作者
浏览器使用 Chrome DevTools 协议 在浏览器级别拦截请求。使用服务工作线程在浏览器级别拦截请求。

集成

¥Integration

page.route()模拟服务工作者
不需要对代码进行任何更改。Playwright 原生可用。不需要对代码进行任何更改。
适用于任何请求客户端,无需额外配置。适用于任何请求客户端,无需额外配置。

定义

¥Definition

page.route()

Playwright 中的 page.route() 函数利用 route.fulfill()route.continue() 等自定义方法让你更好地控制请求。

¥The page.route() function in Playwright utilizes custom methods like route.fulfill() and route.continue() to give you more control over the request.

page.route('/fruits', async (route) => {
  const request = route.request()
 
  if (request.method === 'POST') {
    const response = await route.fetch()
    const json = await response.json()
    json.push({ name: 'Playwright' })
 
    return route.fulfill({ response, json })
  }
 
  route.continue()
})

模拟服务工作者

¥Mock Service Worker

import { bypass } from 'msw'
 
http.post('/fruits', async ({ request }) => {
  const response = await fetch(bypass(request))
  const json = await response.json()
  json.push({ name: 'Mock Service Worker' })
 
  return HttpResponse.json(json, response)
})

MSW 中 route.continue() 的替代方案是从响应解析器中不返回任何内容。但由于我们可以将请求拦截范围缩小到方法(POST)和路径(/fruits),我们的请求处理程序永远不会关注其他请求。

¥The alternative for route.continue() in MSW is simply returning nothing from a response resolver. But since we can narrow down the request interception to both the method (POST) and path (/fruits), our request handler never concerns itself with other requests.

MSW 使用自定义 bypass() 函数封装任何给定的 Request 实例,以防止它受到任何其他匹配的请求处理程序的影响。

¥MSW uses the custom bypass() function that wraps any given Request instance to prevent it from being affected by any other otherwise matching request handlers.