为啥不显示我的 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 钩子?

如何将自定义消息添加到 Jest 期望?

创建自定义 codeigniter 验证规则

带有路径变量和蚂蚁匹配器的 Spring Security 自定义方法

不知道为啥我的自定义 UICollectionViewCell 不起作用?