在jest.toHaveBeenCalledWith中松散匹配一个值

dot*_*ter 6 jestjs

我有一个分析跟踪器仅将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()
})
Run Code Online (Sandbox Code Playgroud)

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"}
Run Code Online (Sandbox Code Playgroud)

我已经看过玩笑扩展, 但没有发现对我的用例有用的东西。

Lia*_*iam 30

重申cl0udw4lk3r 的评论,因为我发现这在我的场景中最有用:

如果您有一个接受多个参数(而不是对象)的方法,并且您只想匹配其中一些参数,那么您可以使用expectobject

例子

我想测试的方法:

client.setex(key, ttl, JSON.stringify(obj));
Run Code Online (Sandbox Code Playgroud)

我想确保将正确的值传递到keyandttl但我不关心传入的对象是什么。所以我设置了一个间谍:

const setexSpy = jest.spyOn(mockClient, "setex");
Run Code Online (Sandbox Code Playgroud)

然后我可以预期这种情况:

expect(setexSpy).toHaveBeenCalledWith('test', 99, expect.anything());
Run Code Online (Sandbox Code Playgroud)

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


Nat*_*ner 21

我最喜欢的方式。您可以使用扩展运算符...来扩展您正在检查的对象,然后覆盖(或添加)一个或多个值。

这是一个示例,显示如何将“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)
  })
Run Code Online (Sandbox Code Playgroud)

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

expect(track).toHaveBeenCalledWith(
  {
    ...expected, 
    intervalInMilliseconds: expect.any(Number), 
    category: expect.any(String)
  })
Run Code Online (Sandbox Code Playgroud)


Rom*_*nko 12

这可以通过不对称匹配器完成(在Jest 18中引入)

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

如果使用,jest-extended您可以做类似的事情

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


Her*_*kov 8

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

  • 看来你也可以使用“expect.anything”:https://jestjs.io/docs/en/expect.html#expectanything (2认同)