模拟响应
了解如何模拟 HTTP 响应。
基础知识
¥Basics
Mock Service Worker 尊重 WHATWG Fetch API 规范,这意味着你构建的模拟响应与你进行 fetch
调用时收到的响应相同。如果你对 Response
类感到满意,你可以跳过本节之后的所有内容 - 你已经知道如何声明响应。
¥Mock Service Worker respects the WHATWG Fetch API specification, which means that the mocked responses you construct are the same responses you would receive when making a fetch
call. If you are comfortable with the Response
class, you can skip everything past this section—you know how to declare responses already.
要响应被拦截的请求,请从匹配的请求处理程序返回一个有效的 Response
实例:
¥To respond to an intercepted request, return a valid Response
instance from the matching request handler:
import { http } from 'msw'
export const handlers = [
// Intercept the "GET /resource" request.
http.get('/resource', () => {
// And respond with a "text/plain" response
// with a "Hello world!" text response body.
return new Response('Hello world!')
}),
]
你不需要导入 Response
类,因为它是浏览器和现代版本的 Node.js (v17+) 中全局 Fetch API 的一部分。库支持 Response
实例的任何变体,包括通过 Response.json()
或 Response.error()
等方法创建的简写响应。
¥You don’t need to import the Response
class because it’s a part of the global Fetch API in the browser and modern versions of Node.js (v17+). The library supports any variations of the Response
instances, including shorthand responses created via methods like Response.json()
or Response.error()
.
使用 HttpResponse
类
¥Using HttpResponse
class
尽管你可以使用普通的 Fetch API 响应,但强烈建议你使用库提供的自定义 HttpResponse
类。有两个原因使 HttpResponse
优于原生 Response
:
¥Although you can use plain Fetch API responses, it’s highly recommended you use the custom HttpResponse
class provided by the library. There are two reasons to prefer HttpResponse
over the native Response
:
-
HttpResponse
类封装了用于声明响应的有用简写方法,如HttpResponse.json()
、HttpResponse.xml()
、HttpResponse.formData()
等。¥The
HttpResponse
class encapsulates useful shorthand methods for declaring responses, likeHttpResponse.json()
,HttpResponse.xml()
,HttpResponse.formData()
, etc. -
与原生
Response
类不同,HttpResponse
类通过在模拟响应上设置Set-Cookie
标头来支持模拟响应 cookie。¥Unlike the native
Response
class, theHttpResponse
class enables support for mocking response cookies by setting theSet-Cookie
header on the mocked response.
下面是相同的 GET /resource
处理程序,但使用 HttpResponse
类:
¥Here’s the same GET /resource
handler but using the HttpResponse
class:
// 1. Import the "HttpResponse" class from the library.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/resource', () => {
// 2. Return a mocked "Response" instance from the handler.
return HttpResponse.text('Hello world!')
}),
]
HttpResponse
与原生Response
类 100% 兼容。在后台,HttpResponse
返回一个简单的 Fetch APIResponse
实例。¥
HttpResponse
is 100% compatible with the nativeResponse
class. Under the hood,HttpResponse
returns a plain Fetch APIResponse
instance.
模拟状态代码和文本
¥Mocking status code and text
在响应初始化器对象中提供 status
和/或 statusText
属性,分别指定模拟响应状态或响应状态代码。
¥Provide the status
and/or statusText
property in the response initializer object to specify a mocked response status or response status code, respectively.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/apples', () => {
return new HttpResponse(null, {
status: 404,
statusText: 'Out Of Apples',
})
}),
]
模拟标头
¥Mocking headers
在响应初始化器对象中提供 headers
属性,以指定模拟响应标头。
¥Provide the headers
property in the response initializer object to specify mocked response headers.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.post('/auth', () => {
return new HttpResponse(null, {
headers: {
'Set-Cookie': 'mySecret=abc-123',
'X-Custom-Header': 'yes',
},
})
}),
]
了解有关构建 标头 的更多信息。
¥Learn more about constructing Headers.
模拟主体
¥Mocking body
你可以使用各种响应主体类型来响应请求:String
、Blob
、FormData
、ReadableStream
和其他(请参阅 Fetch API Response
了解支持的响应主体类型)。
¥You can respond to requests with various response body types: String
, Blob
, FormData
, ReadableStream
, and others (see Fetch API Response
for supported response body types).
下面,让我们看看如何模拟一些最常见的 HTTP 响应主体。
¥Below, let’s take a look at how to mock some of the most common HTTP response bodies.
文本响应
¥Text responses
HTTP 中最基本的响应是文本响应。将你希望用来响应的文本字符串作为参数提供给 HttpResponse
构造函数,以创建模拟文本响应:
¥The most basic response in HTTP is a text response. Provide the text string you wish to respond with as an argument to the HttpResponse
constructor to create a mocked text response:
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/name', () => {
return new HttpResponse('John')
}),
]
你还可以使用
HttpResponse.text()
简写静态方法。¥You can also use
HttpResponse.text()
shorthand static method.
JSON 响应
¥JSON responses
更常见的响应主体类型是 JSON。将你希望用来响应的 JSON 作为参数提供给 HttpResponse.json()
静态方法,以创建模拟 JSON 响应:
¥A much more common response body type is JSON. Provide the JSON you wish to respond with as an argument to the HttpResponse.json()
static method to create a mocked JSON response:
import { http, HttpResponse } from 'msw'
export const handlers = [
http.post('/auth', () => {
// Note that you DON'T have to stringify the JSON!
return HttpResponse.json({
user: {
id: 'abc-123',
name: 'John Maverick',
},
})
}),
]
我们建议使用
HttpResponse.json()
简写静态方法自动使Content-Type
和Content-Length
响应标头与你正在使用的响应 JSON 主体保持同步。¥We recommend using the
HttpResponse.json()
shorthand static method to automatically keep theContent-Type
andContent-Length
response headers in-sync with the response JSON body you’re using.
流响应
¥Stream responses
你可以使用 ReadableStream
进行响应,以将任何数据流回客户端。
¥You can respond with a ReadableStream
to stream any data back to the client.
Streaming
Respond with a `ReadableStream`.
其他响应
¥Other responses
你可以使用 MSW 描述许多其他响应主体类型,例如 XML、Blob
、ArrayBuffer
或 FormData
。请参阅 HttpResponse
API 以了解有关使用其他响应主体类型的更多信息。
¥There are many other response body types you can describe with MSW, like XML, Blob
, ArrayBuffer
, or FormData
. Please refer to the HttpResponse
API to learn more about using other response body types.
HttpResponse
API reference for the `HttpResponse` class.
模拟错误响应
¥Mocking error responses
从响应解析器构造并返回有效的错误响应以模拟错误响应。
¥Construct and return a valid error response from a response resolver to emulate an error response.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/user', () => {
// Respond with "401 Unauthorized" to "GET /user" requests.
return new HttpResponse(null, { status: 401 })
}),
]
模拟网络错误
¥Mocking network errors
使用 Response.error()
或 HttpResponse.error()
静态方法引发网络错误。与错误响应不同,网络错误将停止请求执行并将该请求标记为失败。实际上,在构建无效请求或请求无法解析的主机名时,你可能会遇到网络错误。
¥Use the Response.error()
or HttpResponse.error()
static method to raise a network error. Unlike an error response, a network error will halt the request execution and will mark that request as failed. In practice, you may experience network errors when constructing an invalid request or requesting hostnames that cannot be resolved.
import { http, HttpResponse } from 'msw'
export const handlers = [
http.post('/checkout/cart', () => {
return HttpResponse.error()
}),
]
抛出响应
¥Throwing responses
你可以在响应解析器中的任何点抛出 Response
实例。发生这种情况时,请求处理会短路,抛出的响应将作为模拟响应返回。
¥You can throw a Response
instance at any point in the response resolver. When that happens, the request handling short-circuits, and the thrown response is returned as the mocked response.
import { http, HttpResponse } from 'msw'
http.post('/login', ({ request }) => {
if (!request.headers.has('cookie')) {
throw new HttpResponse(null, { status: 400 })
}
})
这对于在处理请求时实现中间件模式特别方便。
¥This is particularly handy to implement a middleware pattern when handling requests.
async function isAuthenticated(request) {
if (!request.headers.has('cookie')) {
throw new HttpResponse(null, { status: 400 })
}
}
http.post('/login', async ({ request }) => {
await isAuthenticated(request)
return new HttpResponse(null, {
status: 302,
headers: {
Location: '/dashboard',
},
})
})
请注意,任何非响应异常都将转换为
500 Internal Server Error
响应,类似于服务器运行时发生的未处理的拒绝。¥Note that any non-response exceptions will be translated to
500 Internal Server Error
responses, similar to an unhandled rejection happening on server runtime.
相关材料
¥Related materials