避免请求断言

测试时,可能很想针对拦截的请求编写断言。此类断言的示例可能包括:

¥When testing, it may be tempting to write assertions against the intercepted request. Examples of such assertions may include:

  • 检查测试代码是否执行了某个请求;

    ¥Check that the tested code has performed a certain request;

  • 检查请求是否使用正确的 URL/参数/主体/等执行;

    ¥Check that the request was performed with the correct URL/parameters/body/etc;

  • 检查是否调用了特定的请求处理程序。

    ¥Check that a specific request handler was called.

我们强烈反对这样的断言,因为它们代表了实现细节测试,并会诱使你测试应用的编写方式而不是它的作用。使用 MSW 进行测试时,请将此视为默认建议。

¥We highly discourage against such assertions as they represent implementation detail testing and sway you into testing how your application is written instead of what it does. Treat this as the default recommendation when testing with MSW.

请求有效性

¥Request validity

断言请求有效性的最佳方法是忠实地描述其在请求处理程序中的行为。

¥The best way to assert the request’s validity is faithfully describing its behavior in request handlers.

例如,在描述登录端点时,你不需要在测试中断言请求正文包含 email 表单数据字段。相反,如果请求处理程序中没有错误响应,则返回错误响应:

¥For example, when describing a login endpoint, you don’t need to assert that the request body contained the email form data field in your test. Instead, return an error response if it didn’t in your request handler:

export const handlers = [
  http.post('/login', async ({ request }) => {
    const data = await request.formData()
    const email = data.get('email')
 
    if (!email) {
      return new HttpResponse('Missing email', { status: 400 })
    }
  }),
]

这不仅是断言请求有效性的正确方法,错误处理还使你的请求处理程序更接近生产行为。

¥Not only is this the right way to assert the request’s validity, error handling also brings your request handlers closer to the production behavior.

如果测试代码恰好在其 FormData 主体中遗漏了 email 键,你的应用将收到错误响应,从而使你的基于 UI 的断言失败,表明存在问题。

¥If the tested code happens to miss the email key its FormData body, your application will receive an error response, making your UI-based assertions fail, indicating an issue.

这对于更有针对性的测试也适用,因为你可以在每个测试中使用 网络覆盖 指定额外的请求处理程序逻辑。

¥This stands true for a more targeted tests as well since you can specify additional request handler logic using network overrides on a per-test basis.

未处理的请求

¥Unhandled requests

要确保你的测试代码不会执行任何未知的 HTTP 请求,请使用 worker.start()/server.listen()onUnhandledRequest 选项:

¥To make sure your tested code doesn’t perform any unknown HTTP requests, use the onUnhandledRequest option of the worker.start()/server.listen():

server.listen({
  // This tells MSW to throw an error whenever it
  // encounters a request that doesn't have a
  // matching request handler.
  onUnhandledRequest: 'error',
})

这是在测试设置文件中设置的特别有用的选项。

¥This is particularly useful option to set in your test setup file.

异常

¥Exceptions

话虽如此,在某些情况下,执行的请求在应用中没有任何可以断言的迹象。这些通常是针对第三方服务的单向请求,例如分析或监控。

¥That being said, there are scenarios when a performed request has no indication in the application that can be asserted. These are usually one-way requests against third-party services, like analytics or monitoring.

对于这些情况,请使用 生命周期事件 API 对请求/响应提供直接断言。

¥For those cases, please use the Life-cycle events API to provide direct assertions on requests/responses.