You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何扩展Jest/Expect的isEqual匹配器以预处理预期值?

这问题我太懂了!想要让Jest的isEqual匹配器自动帮你把预期的多行字符串用indentToFirstLine处理,又不想每次手动调用,还得保留原匹配器的所有功能?安排!

核心思路

咱们可以通过Jest的expect.extend() API自定义(或者扩展原有)匹配器,在内部先对预期值做转换,再调用原生的isEqual逻辑做比较——既省了重复代码,又完全保留原匹配器的校验能力和错误提示。

具体实现步骤

1. 基础版:自定义新匹配器(不覆盖原生)

如果不想动原生的isEqual,咱们可以新建一个带专属功能的匹配器,比如叫isEqualWithIndentFix:

// 先导入需要的工具函数
const { indentToFirstLine } = require('indent-to-first-line');

// 扩展Jest匹配器
expect.extend({
  isEqualWithIndentFix(received, expected) {
    // 只对字符串类型的预期值做转换,非字符串原样保留
    const processedExpected = typeof expected === 'string' 
      ? indentToFirstLine(expected) 
      : expected;
    
    // 调用Jest内部的原生isEqual逻辑做比较
    const compareResult = this.equals(received, processedExpected);

    // 构建匹配结果的提示信息,和原生风格保持一致
    if (compareResult.pass) {
      return {
        pass: true,
        message: () => `expected ${this.utils.printReceived(received)} not to equal ${this.utils.printExpected(processedExpected)}`
      };
    } else {
      return {
        pass: false,
        message: () => 
          `expected ${this.utils.printReceived(received)} to equal ${this.utils.printExpected(processedExpected)}\n\n未处理的原始预期值:${this.utils.printExpected(expected)}`
      };
    }
  }
});

2. 进阶版:覆盖原生isEqual(全局生效)

如果你希望所有用到isEqual的地方都自动生效这个转换,可以直接覆盖原生匹配器(注意:谨慎操作,确保不会影响其他非字符串类型的测试):

const { indentToFirstLine } = require('indent-to-first-line');

expect.extend({
  isEqual(received, expected) {
    const processedExpected = typeof expected === 'string' 
      ? indentToFirstLine(expected) 
      : expected;
    
    const compareResult = this.equals(received, processedExpected);

    return {
      pass: compareResult.pass,
      message: compareResult.pass
        ? () => `expected ${this.utils.printReceived(received)} not to equal ${this.utils.printExpected(processedExpected)}`
        : () => `expected ${this.utils.printReceived(received)} to equal ${this.utils.printExpected(processedExpected)}`
    };
  }
});

3. 全局加载匹配器

把上面的代码放到一个单独的文件里(比如jest.setup.js),然后在Jest配置里设置自动加载:

// jest.config.js
module.exports = {
  setupFilesAfterEnv: ['./jest.setup.js'],
};

这样所有测试文件都会自动用上这个扩展后的匹配器啦!

测试示例

现在你在测试里就可以直接用多行字符串写预期值了:

test('多行字符串匹配测试', () => {
  const actualOutput = 'Hello\n  Jest\n    Indent Fix';
  
  // 直接写带换行的预期字符串,不用手动处理缩进
  const expectedOutput = `
Hello
  Jest
    Indent Fix
`;

  // 用自定义匹配器的情况
  expect(actualOutput).isEqualWithIndentFix(expectedOutput);
  
  // 如果覆盖了原生isEqual,直接用原语法就行
  // expect(actualOutput).toEqual(expectedOutput);
});

内容的提问来源于stack exchange,提问作者Undistraction

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:53:07