能否为Jest expect断言添加自定义修饰符?如何实现?
实现Jest自定义expect修饰符,复用匹配器处理JSON响应
完全可行,你可以通过扩展Jest的expect实例原型,实现自定义链式修饰符,把JSON解析逻辑抽离出来,直接复用现有匹配器。
具体实现步骤
1. 配置Jest启动文件
先确保你有一个Jest的启动配置文件(比如setupTests.js或setupTests.ts),并在jest.config.js中指定它:
// jest.config.js module.exports = { // 其他配置... setupFilesAfterEnv: ['./setupTests.js'], };
2. 实现自定义修饰符
在启动文件中添加以下代码,给expect实例添加.jsonBody修饰符:
// setupTests.js Object.defineProperty(expect.prototype, 'jsonBody', { get() { // 获取原始的响应字符串 const originalActual = this.getState().actual; // 解析JSON,添加错误处理 let parsedJson; try { parsedJson = JSON.parse(originalActual); } catch (error) { throw new Error(`JSON解析失败: ${error.message}\n原始内容: ${originalActual}`); } // 创建新的expect实例,指向解析后的JSON const newExpectInstance = expect(parsedJson); // 继承原有的修饰符状态(比如.not) if (this.isNot) { newExpectInstance.not; } return newExpectInstance; }, });
3. TypeScript类型支持(可选)
如果使用TypeScript,需要扩展Jest的全局类型,避免类型报错。在setupTests.ts或单独的类型声明文件中添加:
declare global { namespace jest { interface Expect { jsonBody: Matchers<any>; } } } export {};
使用方式
现在你可以直接用链式调用替代原来的自定义匹配器:
// 原写法 expect(someStringResponse).toHaveJsonBodyIncludingSameMembers(['a', 'b']); // 新写法 expect(someStringResponse).jsonBody.toIncludeSameMembers(['a', 'b']); // 支持.not修饰符 expect(someStringResponse).not.jsonBody.toIncludeSameMembers(['c', 'd']); // 复用所有jest-extended的匹配器 expect(someStringResponse).jsonBody.toSatisfy((body) => body.id === 123); expect(someStringResponse).jsonBody.toIncludeAllMembers(['a', 'b']);
核心逻辑说明
- 通过
Object.defineProperty给expect.prototype添加jsonBody的getter,每次访问时自动触发JSON解析。 - 解析过程加入try-catch,抛出清晰的错误信息,方便调试格式错误的响应。
- 继承原实例的
.isNot状态,保证修饰符组合使用的正确性。
内容的提问来源于stack exchange,提问作者Takezoshi
相关产品推荐
相关产品推荐

