【问题标题】:Using Jest property matchers on arrays of objects在对象数组上使用 Jest 属性匹配器
【发布时间】:2019-01-08 04:30:18
【问题描述】:

我正在尝试使用 Jest 的新 Property Matcher 功能(自 Jest 23.0.0 起)来匹配包含生成字段的对象数组。我尝试使用expect.arrayContainingexpect.objectContaining 来放置一个普通对象和一个匹配器定义,就像我在手动匹配时一样。目前有没有办法做到这一点?

const sportsBallPeople = [
  {
    createdAt: new Date(),
    name: 'That one famous guy from Cleveland'
  },
  {
    createdAt: new Date(),
    name: 'That tall guy'
  }
];
expect(sportsBallPeople).toMatchSnapshot(<something goes here>);

【问题讨论】:

  • 我认为当前版本的 Jest 不可能。查看代码,似乎属性匹配仅适用于对象快照,数组只能与精确副本匹配。
  • 您愿意使用不同的方法代替 Jest 的新属性匹配器功能吗?由于当前版本不支持此功能,因此我在将对象传递给 expect() 之前省略了这些属性。

标签: javascript testing jestjs


【解决方案1】:

要将快照属性匹配器应用于每个数组条目而不为每个条目创建单独的断言,我们可以创建一个长度等于填充匹配器定义的值长度的数组:

it('should return first 10 notes by default', async () => {
  const noteMatcher = {
    createdAt: expect.any(String),
    updatedAt: expect.any(String),
  }
  const response = await app.inject({
    method: 'GET',
    url: `/examples/users/1/notes`,
  })
  const payload = response.json()
  const { length } = payload.data

  expect(response.statusCode).toMatchInlineSnapshot(`200`)
  expect(length).toBe(10)
  expect(payload).toMatchSnapshot({
    data: new Array(length).fill(noteMatcher),
  })
})

将生成以下快照:

exports[`should return first 10 notes by default 2`] = `
Object {
  "data": Array [
    Object {
      "createdAt": Any<String>,
      "deletedAt": null,
      "id": 1,
      "note": "Note 1",
      "title": "Title 1",
      "updatedAt": Any<String>,
      "userID": 1,
    },
    Object {
      "createdAt": Any<String>,
      "deletedAt": null,
      "id": 2,
      "note": "Note 2",
      "title": "Title 2",
      "updatedAt": Any<String>,
      "userID": 1,
    },
    // 8 omitted entries
  ],
  "success": true,
}
`;

【讨论】:

    【解决方案2】:

    toMatchObject 适用于数组,因为数组是对象

    expect(receivedArray).toMatchObject(expectedArray)

    【讨论】:

      【解决方案3】:

      感谢您的提示。 通常,作为测试,您可以控制输入,从而使以下内容变得可行。

      describe.only('Something', () => {
        it.only('should do something', () => {
          const x = {
            a: false,
            b: true,
            c: 157286400,
          };
          const results = functionBeingTesting(x, 84);
          expect(results[0]).toMatchInlineSnapshot({
              createdAt: expect.any(Number),
              updatedAt: expect.any(Number)
            },
            `
              Object {
                "createdAt": Any<Number>,
                "a": false,
                "b": true,
                "updatedAt": Any<Number>,
                "value": "0",
              }
            `,
          );
          expect(results[1]).toMatchInlineSnapshot({
              createdAt: expect.any(Number),
              updatedAt: expect.any(Number)
            },
            `
              Object {
                "createdAt": Any<Number>,
                "a": false,
                "b": true,
                "updatedAt": Any<Number>,
                "value": "1",
              }
            `,
          );
          expect(results[2]).toMatchInlineSnapshot({
              createdAt: expect.any(Number),
              updatedAt: expect.any(Number)
            },
            `
              Object {
                "createdAt": Any<Number>,
                "a": false,
                "b": true,
                "updatedAt": Any<Number>,
                "value": "1",
              }
            `,
          );
        });
      });

      【讨论】:

        【解决方案4】:

        版本信息

        如问题中所述,Jest 23.0.0 中引入了属性匹配器。请注意,截至今天(2018 年 8 月 5 日),使用 create-react-app 引导的应用程序仍为

        对象

        下面是一个对单个对象使用属性匹配器的示例:

        test('sportsBallPerson', () => {
          expect(sportsBallPeople[0]).toMatchSnapshot({
            createdAt: expect.any(Date)
          })
        });
        

        生成的快照:

        exports[`sportsBallPerson 1`] = `
        Object {
          "createdAt": Any<Date>,
          "name": "That one famous guy from Cleveland",
        }
        `;
        

        这将正确地将 createdAt 匹配到任何日期,并将名称与“来自克利夫兰的那个著名人物”完全匹配。

        阵列

        要使用属性匹配器测试对象数组,请使用 forEach 循环遍历数组并分别对每个对象进行快照测试:

        test('sportsBallPeople', () => {
          sportsBallPeople.forEach((sportsBallPerson) => {
            expect(sportsBallPerson).toMatchSnapshot({
              createdAt: expect.any(Date)
            });
          });
        });
        

        生成的快照:

        exports[`sportsBallPeople 1`] = `
        Object {
          "createdAt": Any<Date>,
          "name": "That one famous guy from Cleveland",
        }
        `;
        
        exports[`sportsBallPeople 2`] = `
        Object {
          "createdAt": Any<Date>,
          "name": "That tall guy",
        }
        `;
        

        forEach 确保按顺序测试对象,并且如上所述对每个对象进行适当的快照测试。

        其他信息

        有趣的是,使用属性匹配器直接测试数组不能正常工作并且有意想不到的副作用。

        我第一次尝试测试数组是创建以下测试:

        test('sportsBallPeople as array', () => {
          expect(sportsBallPeople).toMatchSnapshot([
            { createdAt: expect.any(Date) },
            { createdAt: expect.any(Date) }
          ]);
        });
        

        它生成了以下快照:

        exports[`sportsBallPeople as array 1`] = `
        Array [
          Object {
            "createdAt": Any<Date>,
          },
          Object {
            "createdAt": Any<Date>,
          },
        ]
        `;
        

        这是不正确的,因为缺少名称属性,但测试仍然通过(Jest v23.4.2)。即使更改了名称并添加了其他属性,测试也通过了。

        更有趣的是,一旦执行此测试,任何使用属性匹配器的后续测试都会受到不利影响。例如,将此测试放在对对象循环的测试之前会将这些快照更改为以下内容:

        exports[`sportsBallPeople 1`] = `
        Object {
          "createdAt": Any<Date>,
        }
        `;
        
        exports[`sportsBallPeople 2`] = `
        Object {
          "createdAt": Any<Date>,
        }
        `;
        

        总之,直接传递一个数组以与属性匹配器一起使用是行不通的,并且可能会对使用属性匹配器的其他快照测试产生负面影响。

        【讨论】:

        • 感谢您的实验,在自己玩了一些之后,我得出了相同的结论。我想我会把它作为 Jest 跟踪器的功能请求。
        • @giodamelio 你能分享功能请求链接吗?如果你创建了它?
        • 尚未调查,但如果that MR 还没有进入主实验阶段,则后一种选项现在可能有效。
        猜你喜欢
        • 2018-02-16
        • 2022-08-18
        • 1970-01-01
        • 1970-01-01
        • 2010-09-05
        • 2020-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多