【问题标题】:Is It Possible To Extend A Jest / Expect Matcher是否可以扩展 Jest / Expect Matcher
【发布时间】:2018-08-04 15:14:29
【问题描述】:

我想扩展 Jest 的 isEqual 匹配器,以便在比较之前转换预期值(这允许我在测试中使用多行字符串)。我需要做的就是通过库中的indentToFirstLine 函数运行预期值:indent-to-first-line,然后将其传递给isEqual。显然,我不想在需要它的任何地方都这样做,因此将它折叠到匹配器中是有意义的,并且由于我想要与 Jest / Expect 的 isEqual 匹配器相同的功能,因此使用它是有意义的。

我尝试了以下方法:

import indentToFirstLine from 'indent-to-first-line'
import expect from 'expect'

const toEqualMultiline = (received, expectedTemplateString) => {
  const expected = indentToFirstLine(expectedTemplateString)
  return expect(received).toEqual(expected)
}

export default toEqualMultiline

然而expect(received).toEqual(expected)没有返回值,所以我的匹配器在undefined中返回的值,导致Jest出错:

匹配器函数的意外返回。 Matcher 函数应返回以下格式的对象: {消息?:字符串 |函数,通过:布尔} 返回“未定义”

我是否可以在自己的匹配器中使用toEqual

【问题讨论】:

    标签: javascript testing jasmine jestjs matcher


    【解决方案1】:

    您可以使用expect.extend() 来做到这一点。如果您使用的是,则可以将此示例代码放在下面的setupTests.ts 中,以便将其应用于您运行的所有测试:

    expect.extend({
      toBeWithinRange(received, min, max) {
        const pass = received >= min && received <= ceiling
        return {
          message: () =>
            `expected ${received} to be in range ${floor} - ${ceiling}`,
          pass,
        }
      },
    })
    

    用法

    it('should fail', () => {
      expect(13).toBeWithinRange(1, 10)
    })
    

    运行上面的测试时,输出如下:

    但我们可以做得更好。看看内置的匹配器是如何显示错误信息的:

    如您所见,错误更容易阅读,因为 expectedreceived 值具有不同的颜色,并且上面有一个匹配器提示来指示哪个是哪个。

    为此,我们需要安装这个包jest-matcher-utils 并导入几个方法来漂亮地打印匹配器提示和值:

    import { printExpected, printReceived, matcherHint } from "jest-matcher-utils"
    
    const failMessage = (received, min, max) => () => `${matcherHint(
      ".toBeWithinRange",
      "received",
      "min, max"
    )}
    
    Expected value to be in range:
      min: ${printExpected(min)}
      max: ${printExpected(max)}
    Received: ${printReceived(received)}`
    
    expect.extend({
      toBeWithinRange(received, min, max) {
        const pass = received >= min && received <= max
    
        return {
          pass,
          message: failMessage(received, min, max),
        }
      },
    })
    

    现在看起来好多了,可以帮助您更快地发现问题

    然而,当你否定断言时,上面的代码中有一个小错误

    expect(3).not.toBeWithinRange(1, 10)
    

    输出是.toBeWithinRange 而不是.not.toBeWithinRange

    expect(received).toBeWithinRange(min, max)
    
    Expected value to be in range:
      min: 1
      max: 10
    Received: 3
    

    要解决这个问题,您可以根据pass 值有条件地添加否定词

    const failMessage = (received, min, max, not) => () => `${matcherHint(
      `${not ? ".not" : ""}.toBeWithinRange`,
      "received",
      "min, max"
    )}
    
    Expected value${not ? " not " : " "}to be in range:
      min: ${printExpected(min)}
      max: ${printExpected(max)}
    Received: ${printReceived(received)}`
    
    toBeWithinRange(received, min, max) {
      const pass = received >= min && received <= max
    
      return {
        pass,
        message: failMessage(received, min, max, pass),
      }
    },
    

    现在重新运行测试,你会看到:

    如果false则通过

    expect(3).not.toBeWithinRange(1, 10)
    
    expect(received).not.toBeWithinRange(min, max)
    
    Expected value not to be in range:
      min: 1
      max: 10
    Received: 3
    

    如果true则通过

    expect(13).toBeWithinRange(1, 10)
    
    expect(received).toBeWithinRange(min, max)
    
    Expected value to be in range:
      min: 1
      max: 10
    Received: 13
    

    【讨论】:

    【解决方案2】:

    如果您正在使用 jest 并将该匹配器传递给 expect.extend,您可以使用提供的执行上下文来执行 jest equals 方法,如下所示:

    import indentToFirstLine from 'indent-to-first-line'
    
    export default function toEqualMultiline(received, expectedTemplateString) {
        const expected = indentToFirstLine(expectedTemplateString);
        return {
            message: () => `expected ${received} to equals multiline ${expected}`,
            pass: this.equals(received, expected)
        };
    }
    

    【讨论】:

      猜你喜欢
      • 2010-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-08
      • 2011-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多