拦截请求
通过一个叫做**request handler**的函数实现请求拦截,即 `http.get(predicate, resolver)`- 参数predicate:【字符串|正则】需要拦截的目标请求地址
- 参数resolver:【函数】决定如何处理拦截请求
mock响应
原生的Response
msw遵循fetch的规范,可以使用fetch原生的Response类,同时也可以支持Response实例,其中包括通过`Response.json()` or `Response.error()`这些方法创建的responses实例。import { http } from 'msw'
export const handlers = [
http.get('/resource', () => {
// "text/plain" 类型
return new Response('Hello world!')
}),
]
使用msw的HttpResponse类【!!!推荐】
- 封装了许多原生的方法 - 支持mock的时候通过Set-Cookie头来模拟响应cookieimport { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/resource', () => {
return HttpResponse.text('Hello world!')
}),
]
模拟请求状态码和状态文案等
import { http, HttpResponse } from 'msw'
export const handlers = [
http.get('/apples', () => {
return new HttpResponse(null, {
status: 404,
statusText: 'Out Of Apples',
headers:{
'Set-Cookie': 'mySecret=abc-123',
'X-Custom-Header': 'yes',
}
})
}),
]
模拟响应体
response body类型:json、Blob, FormData, ReadableStream等import { http, HttpResponse } from 'msw'
export const handlers = [
http.post('/auth', () => {
return HttpResponse.json({
user: {
id: 'abc-123',
name: 'John Maverick',
},
})
}),
]
模拟网络错误
使用 Response.error() 或者 HttpResponse.error()这些静态方法实现import { http, HttpResponse } from 'msw'
export const handlers = [
http.post('/checkout/cart', () => {
return HttpResponse.error()
}),
]
和ts搭配使用
所有处于http这个namespace的request handler都接受3个范型参数:http.get<Params, RequestBodyType, ResponseBodyType, Path>(path, resolver)
- Params:需要传给实际接口的请求参数
- RequestBodyType:请求体
- ResponseBodyType:实际接口返回的响应类型
import { http, HttpResponse } from 'msw'
type AddCommentParams = {
postId: string
}
type AddCommentRequestBody = {
author: User
comment: string
}
type AddCommentResponseBody = {
commentUrl: string
}
http.post<
AddCommentParams,
AddCommentRequestBody,
AddCommentResponseBody,
'/post/:postId'
>('/post/:postId', async ({ params, request }) => {
const { postId } = params
const commentData = await request.json()
commentData.comment
return HttpResponse.json({
commentUrl: `/post/${postId}?commentId=${crypto.randomUUID()}`,
})
})
request handler进阶使用
import { http, HttpResponseResolver, HttpResponse } from 'msw'
type SdkRequest = {
transactionId: string
}
type SdkResponse = {
transactionId: string
data: { ok: boolean }
}
function handleSdkRequest(
resolver: HttpResponseResolver<never, SdkRequest, SdkResponse>
) {
return http.post('https://some-sdk.com/internal/request', resolver)
}
export const handlers = [
handleSdkRequest(async ({ request }) => {
const data = await request.json()
//响应的json必须符合SdkResponse这个类型.
return HttpResponse.json({
// request body被限制为SdkRequest
transactionId: data.transactionId,
data: { ok: true },
})
}),
]
response resolver的进阶使用
import {
PathParams,
DefaultBodyType,
HttpResponseResolver,
delay,
http,
HttpResponse,
} from 'msw'
function withDelay<
Params extends PathParams,
RequestBodyType extends DefaultBodyType,
ResponseBodyType extends DefaultBodyType
>(durationMs: number, resolver: HttpResponseResolver<Params, RequestBodyType, ResponseBodyType>): HttpResponseResolver<Params, RequestBodyType, ResponseBodyType> {
return async (...args) => {
await delay(durationMs)
return resolver(...args)
}
}
export const handlers = [
http.get<never, never, 'hello world'>(
'/resource',
withDelay(250, ({ request }) => {
// The "ResponseBodyType" generic type provided
// to the "http.get()" request handler propagates
// through the custom "withDelay" response resolver.
return HttpResponse.text('hello world')
})
),
]