为啥不显示我的 Jest 自定义匹配器的“消息”?
Posted
技术标签:
【中文标题】为啥不显示我的 Jest 自定义匹配器的“消息”?【英文标题】:Why is the `message` for my Jest custom matcher not being displayed?为什么不显示我的 Jest 自定义匹配器的“消息”? 【发布时间】:2022-01-10 07:29:15 【问题描述】:我创建了一个 Jest 自定义匹配器。它可以工作(意思是,它应该通过/失败),但我在 Jest 的输出中没有看到 message
。
我做错了什么?我必须做些什么来“启用”消息吗?我是否完全误解了消息应该显示在哪里?
环境:NestJS、Prisma
执行命令:jest --watch
简化代码:
declare global
namespace jest
interface Matchers<R>
toMatchHash(received: string, expected: string): R;
expect.extend(
toMatchJsonHash(received, expected)
return
pass: false,
message: () => `Why doesn't this work?!`,
;
,
);
expect(prisma.name.findMany).toHaveBeenCalledWith(expect.toMatchJsonHash('db0110285c148c77943f996a17cbaf27'));
输出:
● MyService › should pass a test using a custom matcher
expect(jest.fn()).toHaveBeenCalledWith(...expected)
Expected: toMatchJsonHash<db0110285c148c77943f996a17cbaf27>
Received: <Big ol' object redacted for conciseness>
Number of calls: 1
178 |
179 | // @ts-ignore
> 180 | expect(prisma.name.findMany).toHaveBeenCalledWith(expect.toMatchJsonHash('db0110285c148c77943f996a17cbaf27'));
| ^
181 | // expect(prisma.name.findMany).toHaveBeenCalledWith(
182 | // select: type: true, name: true ,
183 | // where:
at Object.<anonymous> (my/my.service.spec.ts:180:32)
我期待看到“为什么这不起作用?!”在输出的某个地方,但我没有。我错过了什么?
【问题讨论】:
显示消息的匹配器是.toHaveBeenCalledWith
,试试expect(some).toMatchHash(other)
。
@jonrsharpe 一定是这样!说得通!不过,我还在“睡觉”;早上很兴奋尝试。但是,使用这种方法,“toMatchHash()”如何访问“调用”信息(参数)?
【参考方案1】:
作为suggested by @jonsharpe,原因是Jest 显示来自“外部”匹配器.toHaveBeenCalledWith()
的消息。
为了解决这个问题,我找到了the source that defines the .toHaveBeenCalledWith()
matcher 并将其代码“合并”到我的自定义匹配器中。
这使我的自定义匹配器能够有效地“扩展”.toHaveBeenCalledWith()
匹配器的功能,包括我自己的自定义代码和消息。
如果它对某人有帮助,我最终为我的特定用例编写的代码是:
declare global
namespace jest
interface Matchers<R>
toHaveBeenCalledWithObjectMatchingHash(expected: string): CustomMatcherResult;
expect.extend(toHaveBeenCalledWithObjectMatchingHash(received, expected)
const isSpy = (received: any) =>
received != null &&
received.calls != null &&
typeof received.calls.all === 'function' &&
typeof received.calls.count === 'function';
const receivedIsSpy = isSpy(received);
const receivedName = receivedIsSpy ? 'spy' : received.getMockName();
const calls = receivedIsSpy
? received.calls.all().map((x: any) => x.args)
: received.mock.calls;
if(calls.length === 0)
return
pass: false,
message: () => `expected the function to be called with an object that hashes to '$expected'. Instead, the function was not called.`,
;
if(calls[0].length === 0)
return
pass: false,
message: () => `expected the function to be called with an object that hashes to '$expected'. Instead, the function was called, but not with any arguments.`,
;
const md5Hash = crypto.createHash('md5');
const receivedHash = md5Hash.update(JSON.stringify(calls[0][0])).digest('hex');
const pass = receivedHash === expected;
if(pass)
return
pass: true,
message: () => `expected the function to not be called with an object that hashes to '$expected'. Instead, the passed object hashes to the same value.`,
;
else
return
pass: false,
message: () => `expected the function to be called with an object that hashes to '$expected'. Instead, the passed object hashes to '$receivedHash'.`,
;
);
【讨论】:
以上是关于为啥不显示我的 Jest 自定义匹配器的“消息”?的主要内容,如果未能解决你的问题,请参考以下文章
如何让 TypeScript 知道自定义 Jest 匹配器?
为啥 jest 不能为我正在测试的自定义 React 钩子提供 useTranslation 钩子?