【问题标题】:Test React component that depends on a Promise with Jest使用 Jest 测试依赖于 Promise 的 React 组件
【发布时间】:2020-01-11 22:27:00
【问题描述】:

我正在尝试更多地了解 JS 测试。

我有一个基本的 React 组件,当它挂载时fetch() 的数据。

运行应用时,组件按预期工作并获取数据。

但是,在使用 Jest 进行测试时,我可以看到调用已发出但承诺总是被拒绝?

我一直在关注this example 以进行以下测试。

不确定用 Jest 模拟承诺,任何指针都会有很大帮助!

组件

import React from 'react';
import './App.scss';
import * as Utils from './Functions';
import Header from './components/Header';
import Loader from './components/Loader';
import Table from './components/Table';

export default class App extends React.Component {
  constructor(props) {
    super(props);
    /*
    Initialise state:
      # Loading: true
    */
    this.state = {
      loading: true,
    };
  }

  /*
    When component mounts, 
    # Call function to get data
    # Set state with promise response
  */
  componentDidMount = () => {
    /* Function to grab data
      I've created a local express server to get around the cors issue
    */
    Utils.initData('http://localhost:8888/mock/all').then(data => {
      // Finally set state to reload component with new data
      this.setState({
        loading: false,
        teams: data,
      })
    })
  }  

  render() {
    const { loading, teams } = this.state;
    return (
      <div id="app">
        <Header />
        <div className="table">
          {loading && (<Loader />)}
          {!loading && (<Table data={teams} loading={loading} />)}
        </div>
      </div>
    );
  }
}

功能

export const initData = (dataURL) => {
  try {
    // Get data using the Fetch API
    return fetch(dataURL).then(
      response => response.json()
    )
      // Then sanitize the data
      .then(data => sanitizeData(data));
  } catch (error) {
    console.warn(error);
    return error;
  }
}
export const sanitizeData = (data) => {
  console.log(data)
  // Do loads of stuff with the data
}

测试

import React from 'react';
import ReactDOM from 'react-dom';
import { shallow, mount } from 'enzyme';
import App from './App';
import Table from './components/Table';
import Header from './components/Header';
import * as Utils from './Functions';

import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

describe('App', () => {
  it('- Renders the header', () => {
    const div = document.createElement('div');
    ReactDOM.render(<Header />, div);
    ReactDOM.unmountComponentAtNode(div);
  });

  it('- Renders the table', () => {
    const div = document.createElement('div');
    ReactDOM.render(<Table />, div);
    ReactDOM.unmountComponentAtNode(div);
  });

  it('- Renders the full app', () => {
    const div = document.createElement('div');
    ReactDOM.render(<App />, div);
    ReactDOM.unmountComponentAtNode(div);
  });
});

describe('Gets data', () => {
  it('fetches data from server when server returns a successful response', () => {
    const mockSuccessResponse = {};
    const mockJsonPromise = Promise.resolve(mockSuccessResponse);
    const mockFetchPromise = Promise.resolve({
      json: () => mockJsonPromise,
    });
    jest.spyOn(global, 'fetch').mockImplementation(() => mockFetchPromise); // 4
    const wrapper = shallow(<App />);                      
    expect(global.fetch).toHaveBeenCalledTimes(1);
    expect(global.fetch).toHaveBeenCalledWith('http://localhost:8888/mock/all');
  });
});

错误信息

应用程序本身没有任何错误,但在测试运行时我得到:

(node:4082) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'forEach' of undefined
[1] (node:4082) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
[1] (node:4082) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

上面提到的 forEach 来自sanitizeData() 函数,因为data 参数在测试时是{}...

【问题讨论】:

    标签: node.js reactjs promise jestjs fetch


    【解决方案1】:

    您将在 mockJsonPromise 中返回 {} 并传递给 sanitizeData() 添加因此 forEach 循环不起作用。而是返回一个包含模拟数据的列表。

        const mockSuccessResponse = {};
        const mockJsonPromise = Promise.resolve(mockSuccessResponse);
        const mockFetchPromise = Promise.resolve({
          json: () => mockJsonPromise,
        });
        jest.spyOn(global, 'fetch').mockImplementation(() => mockFetchPromise);
    

    根据上面的代码response.json() 将解析为mockSuccessResponse{}

    【讨论】:

      猜你喜欢
      • 2021-08-08
      • 2021-12-09
      • 2021-04-20
      • 1970-01-01
      • 2019-02-14
      • 1970-01-01
      • 1970-01-01
      • 2020-10-18
      • 2018-02-15
      相关资源
      最近更新 更多