跳至内容

扩展匹配器

由于 Vitest 与 Chai 和 Jest 都兼容,您可以使用 chai.use API 或 expect.extend,选择您喜欢的任何一种。

本指南将探讨使用 expect.extend 扩展匹配器。如果您对 Chai 的 API 感兴趣,请查看 他们的指南

要扩展默认匹配器,请使用包含您的匹配器的对象调用 expect.extend

ts
expect.extend({
  toBeFoo(received, expected) {
    const { isNot } = this
    return {
      // do not alter your "pass" based on isNot. Vitest does it for you
      pass: received === 'foo',
      message: () => `${received} is${isNot ? ' not' : ''} foo`
    }
  }
})

如果您使用的是 TypeScript,从 Vitest 0.31.0 开始,您可以在环境声明文件中(例如:vitest.d.ts)扩展默认的 Assertion 接口,使用以下代码

ts
import type { Assertion, AsymmetricMatchersContaining } from 'vitest'

interface CustomMatchers<R = unknown> {
  toBeFoo: () => R
}

declare module 'vitest' {
  interface Assertion<T = any> extends CustomMatchers<T> {}
  interface AsymmetricMatchersContaining extends CustomMatchers {}
}

警告

不要忘记在您的 tsconfig.json 中包含环境声明文件。

匹配器的返回值应与以下接口兼容

ts
interface MatcherResult {
  pass: boolean
  message: () => string
  // If you pass these, they will automatically appear inside a diff when
  // the matcher does not pass, so you don't need to print the diff yourself
  actual?: unknown
  expected?: unknown
}

警告

如果您创建了一个异步匹配器,请不要忘记在测试本身中 await 结果(await expect('foo').toBeFoo())。

匹配器函数中的第一个参数是接收到的值(expect(received) 中的值)。其余参数是直接传递给匹配器的参数。

匹配器函数可以访问具有以下属性的 this 上下文

  • isNot

    如果匹配器是在 not 上调用的(expect(received).not.toBeFoo()),则返回 true。

  • promise

    如果匹配器是在 resolved/rejected 上调用的,则此值将包含修饰符的名称。否则,它将是一个空字符串。

  • equals

    这是一个实用程序函数,允许您比较两个值。如果值相等,它将返回 true,否则返回 false。此函数在内部用于几乎所有匹配器。默认情况下,它支持具有非对称匹配器的对象。

  • utils

    这包含一组您可以用来显示消息的实用程序函数。

this 上下文还包含有关当前测试的信息。您也可以通过调用 expect.getState() 来获取它。最有用的属性是

  • currentTestName

    当前测试的完整名称(包括 describe 块)。

  • testPath

    当前测试的路径。