在jest. to HaveBeenCalledWith中松散匹配一个值

hwamh0ep  于 2022-12-08  发布在  Jest
关注(0)|答案(4)|浏览(292)

我有一个分析跟踪器,它只会在1秒后调用,并且带有一个intervalInMilliseconds(持续时间)值为确定性的对象。
如何使用jest.toHaveBeenCalledWith测试对象?

test('pageStats - publicationPage (will wait 1000ms)', done => {
  const track = jest.fn()

  const expected = new PayloadTiming({
    category: 'PublicationPage',
    action: 'PublicationPage',
    name: 'n/a',
    label: '7',
    intervalInMilliseconds: 1000 // or around
  })

  mockInstance.viewState.layoutMode = PSPDFKit.LayoutMode.SINGLE
  const sendPageStats = pageStats({
    instance: mockInstance,
    track,
    remoteId: nappConfig.remoteId
  })

  mockInstance.addEventListener('viewState.currentPageIndex.change', sendPageStats)

  setTimeout(() => {
    mockInstance.fire('viewState.currentPageIndex.change', 2)

    expect(track).toHaveBeenCalled()
    expect(track).toHaveBeenCalledWith(expected)

    done()
  }, 1000)

  expect(track).not.toHaveBeenCalled()
})

expect(track).toHaveBeenCalledWith(expected)失败,并显示:

Expected mock function to have been called with:
      {"action": "PublicationPage", "category": "PublicationPage", "intervalInMilliseconds": 1000, "label": "7", "name": "n/a"}
    as argument 1, but it was called with
      {"action": "PublicationPage", "category": "PublicationPage", "intervalInMilliseconds": 1001, "label": "7", "name": "n/a"}

我已经查看了jest-extended,但没有看到任何对我的用例有用的内容。

pbossiut

pbossiut1#

这可以通过非对称匹配器(在Jest 18中引入)来实现

expect(track).toHaveBeenCalledWith(
  expect.objectContaining({
   "action": "PublicationPage", 
   "category": "PublicationPage", 
   "label": "7",
   "name": "n/a"
  })
)

如果使用jest-extended,则可以执行以下操作

expect(track).toHaveBeenCalledWith(
  expect.objectContaining({
   "action": "PublicationPage", 
   "category": "PublicationPage", 
   "label": "7",
   "name": "n/a",
   "intervalInMilliseconds": expect.toBeWithin(999, 1002)
  })
)
ozxc1zmp

ozxc1zmp2#

您可以使用track.mock.calls[0][0](第一个[0]是调用编号,第二个[0]是参数编号)访问预期的对象以获得更好的Assert。然后您可以使用toMatchObject查找部分匹配的对象,避免使用动态参数,如intervalInMilliseconds

vbkedwbf

vbkedwbf3#

通过cl0udw4lk3r重新迭代注解,因为我发现这在我的场景中最有用:
如果您有一个接受多个参数(而不是对象)的方法,并且您只想匹配其中的一些参数,那么您可以使用expect object

示例

我想测试方法:

client.setex(key, ttl, JSON.stringify(obj));

我想确保正确的值被传递到keyttl,但我不关心传入的对象是什么。因此我设置了一个spy:

const setexSpy = jest.spyOn(mockClient, "setex");

我可以预期这样的场景:

expect(setexSpy).toHaveBeenCalledWith('test', 99, expect.anything());

您还可以使用expect.anyexpect.any(Number))等更强类型的调用。

y4ekin9u

y4ekin9u4#

当然我有偏见,但我认为这是最好的和最干净的方法。你可以使用扩展操作符...来扩展你正在检查的对象,然后覆盖(或添加)一个或多个值。
以下示例显示了如何将“intervalInMilliseconds”预期值覆盖为任意数字

const track = jest.fn()

const expected = new PayloadTiming({
    category: 'PublicationPage',
    action: 'PublicationPage',
    name: 'n/a',
    label: '7',
    intervalInMilliseconds: 1000 // or around
  })

expect(track).toHaveBeenCalledWith(
  {
    ...expected, 
    intervalInMilliseconds: expect.any(Number)
  })

显示如何覆盖两个值的另一个示例

expect(track).toHaveBeenCalledWith(
  {
    ...expected, 
    intervalInMilliseconds: expect.any(Number), 
    category: expect.any(String)
  })

相关问题