如何扩展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
相关产品推荐
相关产品推荐

