Loose 匹配 jest.toHaveBeenCalledWith 中的一个值

我有一个分析跟踪器,只会调用后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 扩展”rel = “ norefrer”> jest 扩展 但是我没有看到任何对我的用例有用的东西。

92067 次浏览

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

这可以通过非对称匹配器来实现(在 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)
})
)

为了重复 评论: cl0udw4lk3r,我发现在我的场景中这是最有用的:

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

例子

我想测试的方法:

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

我希望确保传递到 keyttl的值是正确的,但是我不关心传递的对象是什么。所以我安排了一个间谍:

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

然后我可以期待这样的情景:

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

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

当然我有偏见,但我认为这是最好和最干净的方式。可以使用扩展运算符 ...展开要检查的对象,然后覆盖(或添加)一个或多个值。

下面的示例演示如何将“ intervalInMilliseconds”期望值覆盖到任何 Number

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)
})