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

标签 javascript jquery unit-testing reactjs jestjs

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

//...
componentDidMount: function() {
  $(window).on("resize", function);
}
//..

但是,这会导致我的 Jest 测试出现问题,具体来说:

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

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

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

我可以通过不 mock jQuery 来解决这个问题,但显然这并不完全可取。

最佳答案

这是使用 jestjsenzyme 的单元测试解决方案:

index.tsx:

import React, { Component } from 'react';
import $ from 'jquery';

class SomeComponent extends Component {
  componentDidMount() {
    $(window).on('resize', this.resizeEventHandler);
  }

  resizeEventHandler() {
    console.log('resize event handler');
  }

  render() {
    return <div>some component</div>;
  }
}

export default SomeComponent;

index.spec.tsx:

import React from 'react';
import SomeComponent from './';
import { shallow } from 'enzyme';
import $ from 'jquery';

jest.mock('jquery', () => {
  const m$ = {
    on: jest.fn(),
  };
  return jest.fn(() => m$);
});

describe('36082197', () => {
  afterEach(() => {
    jest.restoreAllMocks();
    jest.resetAllMocks();
  });
  it('should pass', () => {
    const logSpy = jest.spyOn(console, 'log');
    const eventHandlerMap = {};
    ($().on as jest.MockedFunction<any>).mockImplementation((event, handler) => {
      eventHandlerMap[event] = handler;
    });
    const wrapper = shallow(<SomeComponent></SomeComponent>);
    const instance = wrapper.instance();
    expect(wrapper.text()).toBe('some component');
    expect($).toBeCalledWith(window);
    // tslint:disable-next-line: no-string-literal
    expect($(window).on).toBeCalledWith('resize', instance['resizeEventHandler']);
    eventHandlerMap['resize']();
    expect(logSpy).toBeCalledWith('resize event handler');
  });
});

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

 PASS  src/stackoverflow/36082197/index.spec.tsx (12.045s)
  36082197
    ✓ should pass (18ms)

  console.log node_modules/jest-mock/build/index.js:860
    resize event handler

-----------|----------|----------|----------|----------|-------------------|
File       |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
-----------|----------|----------|----------|----------|-------------------|
All files  |      100 |      100 |      100 |      100 |                   |
 index.tsx |      100 |      100 |      100 |      100 |                   |
-----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        14.267s, estimated 15s

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

关于javascript - 测试使用 jQuery 和 window 对象的 React 组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36082197/

相关文章:

javascript - JQuery Click() 函数仅执行一次

unit-testing - 如何对与 Elasticsearch 交互的 go 代码进行单元测试

jquery - 如何将 ASP.NET MVC 3 页面的 HTML 获取到 QUnit 测试中?

javascript - 多个单选按钮表单,单个组,无法检索值

javascript - ionic 2 : How do you reinstantiate @ViewChild if you dismiss the view?

javascript - 根据$(document).width()加载Google广告代码

javascript - 继承自 jQuery UI 对话框并调用覆盖的方法

JavaScript 单元测试。 mock 什么?

javascript - 在laravel中动态添加下拉框。 JavaScript 和 Laravel

javascript - angular - 访问 ngOnInit() 之外的数组