【问题标题】:Loose match one value in jest.toHaveBeenCalledWith松散匹配 jest.toHaveBeenCalledWith 中的一个值
【发布时间】:2019-02-19 13:41:39
【问题描述】:

我有一个分析跟踪器,它只会在 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 但我没有看到任何对我的用例有用的东西。

【问题讨论】:

    标签: jestjs


    【解决方案1】:

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

    这是一个示例,展示了如何将“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)
      })
    

    【讨论】:

      【解决方案2】:

      重新迭代comment by cl0udw4lk3r,因为我发现这在我的场景中最有用:

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

      示例

      我要测试的方法:

      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)) 等来使用更强类型的调用。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

          【讨论】:

          猜你喜欢
          • 2011-09-05
          • 2011-03-08
          • 2017-03-07
          • 1970-01-01
          • 1970-01-01
          • 2014-07-27
          • 2019-08-26
          • 2019-01-02
          • 1970-01-01
          相关资源
          最近更新 更多