测试使用 jQuery 和 window 对象的 React 组件

ttr*_*rmw 6 javascript jquery unit-testing reactjs jestjs

我的 React 组件必须响应resize事件,我使用的是 jQuery,即:

//...
componentDidMount: function() {
  $(window).on("resize", function);
}
//..
Run Code Online (Sandbox Code Playgroud)

但是,这会导致我的 Jest 测试出现问题,特别是:

- TypeError: Cannot read property 'on' of undefined
    at RadiumEnhancer.React.createClass.componentDidMount (bundles/Opportunities/OpportunityPartial.jsx:21:14)
Run Code Online (Sandbox Code Playgroud)

在单步执行测试时,看起来 window 是在 jest 测试中定义的,但$(window)似乎没有返回任何内容。

我的印象是 Jest 会检查所需的模块 (jQuery) 的 API 来构建它的模拟,但是如果我正确理解了问题,这似乎不会发生?

我可以通过不嘲笑 jQuery 来解决这个问题,但显然这不是完全可取的。

sli*_*wp2 1

jestjs这是使用和的单元测试解决方案enzyme

\n\n

index.tsx:

\n\n
import React, { Component } from \'react\';\nimport $ from \'jquery\';\n\nclass SomeComponent extends Component {\n  componentDidMount() {\n    $(window).on(\'resize\', this.resizeEventHandler);\n  }\n\n  resizeEventHandler() {\n    console.log(\'resize event handler\');\n  }\n\n  render() {\n    return <div>some component</div>;\n  }\n}\n\nexport default SomeComponent;\n
Run Code Online (Sandbox Code Playgroud)\n\n

index.spec.tsx:

\n\n
import React from \'react\';\nimport SomeComponent from \'./\';\nimport { shallow } from \'enzyme\';\nimport $ from \'jquery\';\n\njest.mock(\'jquery\', () => {\n  const m$ = {\n    on: jest.fn(),\n  };\n  return jest.fn(() => m$);\n});\n\ndescribe(\'36082197\', () => {\n  afterEach(() => {\n    jest.restoreAllMocks();\n    jest.resetAllMocks();\n  });\n  it(\'should pass\', () => {\n    const logSpy = jest.spyOn(console, \'log\');\n    const eventHandlerMap = {};\n    ($().on as jest.MockedFunction<any>).mockImplementation((event, handler) => {\n      eventHandlerMap[event] = handler;\n    });\n    const wrapper = shallow(<SomeComponent></SomeComponent>);\n    const instance = wrapper.instance();\n    expect(wrapper.text()).toBe(\'some component\');\n    expect($).toBeCalledWith(window);\n    // tslint:disable-next-line: no-string-literal\n    expect($(window).on).toBeCalledWith(\'resize\', instance[\'resizeEventHandler\']);\n    eventHandlerMap[\'resize\']();\n    expect(logSpy).toBeCalledWith(\'resize event handler\');\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

100%覆盖率的单元测试结果:

\n\n
 PASS  src/stackoverflow/36082197/index.spec.tsx (12.045s)\n  36082197\n    \xe2\x9c\x93 should pass (18ms)\n\n  console.log node_modules/jest-mock/build/index.js:860\n    resize event handler\n\n-----------|----------|----------|----------|----------|-------------------|\nFile       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |\n-----------|----------|----------|----------|----------|-------------------|\nAll files  |      100 |      100 |      100 |      100 |                   |\n index.tsx |      100 |      100 |      100 |      100 |                   |\n-----------|----------|----------|----------|----------|-------------------|\nTest Suites: 1 passed, 1 total\nTests:       1 passed, 1 total\nSnapshots:   0 total\nTime:        14.267s, estimated 15s\n
Run Code Online (Sandbox Code Playgroud)\n\n

源代码:https ://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/36082197

\n