【问题标题】:jest mock call object is possibly undefined开玩笑的模拟调用对象可能是未定义的
【发布时间】:2021-07-30 02:54:06
【问题描述】:

这是一个使用mocked function 的简单测试。但我确实收到了模拟调用Object is possibly 'undefined'.ts(2532) 的 ts 错误。我不知道如何摆脱这个错误。 This is the structure 的调用对象,所以我认为我正确处理了它......但显然不是 ts 预期的那样。

import { render, fireEvent } from '@testing-library/react'

const mockSetCheckbox = jest.fn(() => Promise.resolve())

test('should select checkbox', () => {
  // ...
  userEvent.click(checkbox)
  expect(mockSetCheckbox.mock.calls[0][0].variables.input.checkbox).toBe(true)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   Object is possibly 'undefined'.ts(2532)
})

【问题讨论】:

    标签: javascript typescript unit-testing jestjs


    【解决方案1】:

    它是说mockSetCheckbox.mock.calls[0][0] 可能是undefined,因为你可能在做mockSetCheckbox.mock.undefined.variables 而你不能像那样引用undefined

    它试图帮助您,因为无论 calls[0][0] 是什么类型,您的类型都是 undefined 和/或其他类型。

    最简单的解决方法是先检查以确保检查器不会是undefined。如果您不想要一堆ifs,则存在更简洁的快捷方式。

    if(mockSetCheckbox.mock.calls[0][0]) {
       expect(mockSetCheckbox.mock.calls[0][0].variables.input.checkbox).toBe(true)
    }
    

    如果测试 undefined by throwing,您可能还想确保测试失败。由于没有expects 表示“通过”,因此上述内容将静默失败。我更喜欢通过发现问题并在寻找问题后假设一切都很好来做到这一点。

    类似:

    if(mockSetCheckbox.mock.calls[0][0] === undefined) {
        throw "oh no!";
    }
    expect(mockSetCheckbox.mock.calls[0][0].variables.input.checkbox).toBe(true)
    

    其他选项包括:

    expect(mockSetCheckbox.mock.!calls[0][0].variables.checkbox).toBe(true);
    
    // or 
    
    expect((mockSetCheckbox.mock.calls[0][0] as Something).variables.input.checkbox).toBe(true);
    
    // or
    
    let val:Something = mockSetCheckbox.mock.calls[0][0];
    expect(val.variables.input.checkbox).toBe(true);
    
    

    ...其中Something 是包含variables 对象(或any)的任何类型。

    【讨论】:

    • 如果我使用let val = mockSetCheckbox.mock.calls[0][0],我会得到最后一个括号的错误Tuple type '[]' of length '0' has no element at index '0'.ts(2493)
    • 由于这是一个测试用例,我认为非空断言! 最能传达意图。您的示例不太正确,它应该在第二次数组访问之后出现:mockSetCheckbox.mock.calls[0][0]!.variables.checkbox
    • 不幸的是,! 并没有改变任何东西。我可以做mock.calls[0]?[0],但这给了我Property 'variables' does not exist on type 'number[]'
    【解决方案2】:

    我建议您将测试更改为使用.toHaveBeenCalled()

      test("should select checkbox", () => {
        userEvent.click(checkbox)
    
        expect(mockSetCheckbox).toHaveBeenCalledWith(
          expect.objectContaining({
            variables: expect.objectContaining({
              input: expect.objectContaining({
                checkbox: true,
              }),
            }),
          })
        );
      });
    

    这将断言相同,但如果实现以不调用函数的方式发生更改,您将得到更容易理解的错误。

    使用.toHaveBeenCalled() 时会如下所示:

        expect(jest.fn()).toHaveBeenCalledWith(...expected)
    
        Expected: ObjectContaining {"variables": ObjectContaining {"input": ObjectContaining {"checkbox": true}}}
    
        Number of calls: 0
    

    working example

    【讨论】:

      猜你喜欢
      • 2021-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-20
      • 2018-12-30
      • 2018-10-23
      • 2021-04-06
      • 2019-11-19
      相关资源
      最近更新 更多