javascript - 如何在 Jest 测试中比较(匿名)函数?

标签 javascript reactjs react-redux jestjs

我将以下 React 组件连接到 redux 存储。

import React, { Component } from 'react'
import logo from './logo.svg'
import './App.css'
import { connect } from 'react-redux'
import { getWeather } from './actions/WeatherActions'
import WeatherComponent from './components/weatherComponent/WeatherComponent'
import { get } from 'lodash'

export class App extends Component {

  componentDidMount () {
    this.props.dispatch(getWeather())
  }

  render () {
    return (
        <div className="App">
          <div className="App-header">
            <img src={logo} className="App-logo" alt="logo" />
            <h2>Welcome to React</h2>
          </div>
          <WeatherComponent
              weather={{
                location: get(this.props.weatherReducer.weather, 'name'),
                temp: get(this.props.weatherReducer.weather, 'main.temp')
              }}
          />
        </div>
    )
  }
}

export default connect((store) => {
  return {
    weatherReducer: store.weatherReducer,
  }
})(App)

此组件正在使用 componentDidMount 回调调度 getWeather 操作。 getWeather 操作在解析 axios Promise 时返回一个匿名方法。

import { GET_WEATHER_DONE, GET_WEATHER_ERROR } from './ActionTypes'
import axios from 'axios'

export function getWeather () {
  let endpoint = 'http://api.openweathermap.org/data/2.5/weather?q=London&appid=2a345681ddcde393253af927097f5747'

  return function (dispatch) {
    return axios.get(endpoint)
    .then((response) => {
      return dispatch({
        type: GET_WEATHER_DONE,
        payload: response.data
      })
    })
    .catch((error) => {
      return dispatch({
        type: GET_WEATHER_ERROR,
        payload: error.response.data,
        statuscode: error.response.status
      })
    })
  }
}

不,我正在尝试编写一个单元测试,验证在安装时正在调度 getWeather 操作。该测试如下所示并通过。

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import * as actions from './actions/WeatherActions'

describe('app container', () => {
  const store = configureMockStore([thunk])({
    weatherReducer: {
      weather: {}
    }
  })

  const dispatchSpy = jest.fn()
  store.dispatch = dispatchSpy

  it('dispatches getWeather() action upon rendering', () => {
    ReactDOM.render(<App store={store} />, document.createElement('div'))

    expect(dispatchSpy.mock.calls[0][0].toString()).toEqual(actions.getWeather().toString())
  })

})

由于操作返回匿名方法,我需要在模拟上调用 toString 方法来比较操作。

我使用快照测试重新创建了此测试。

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'

describe('app container', () => {
  const store = configureMockStore([thunk])({
    weatherReducer: {
      weather: {}
    }
  })

  const dispatchSpy = jest.fn()
  store.dispatch = dispatchSpy

  it('dispatches correct actions upon rendering', () => {
    ReactDOM.render(<App store={store} />, document.createElement('div'))

    let tree = dispatchSpy.mock.calls.toString()
    expect(tree).toMatchSnapshot();
  })


})

我需要再次调用 toString 方法,产生以下快照。

// Jest Snapshot v1, 

exports[`app container dispatches correct actions upon rendering 1`] = `
"function (dispatch) {
    return _axios2.default.get(endpoint).
    then(response => {
      return dispatch({
        type: _ActionTypes.GET_WEATHER_DONE,
        payload: response.data });

    }).
    catch(error => {
      return dispatch({
        type: _ActionTypes.GET_WEATHER_ERROR,
        payload: error.response.data,
        statuscode: error.response.status });

    });
  }"
`;

现在,当使用 yarn 测试 -- --coverage 运行覆盖率时,我的测试失败,因为 istanbul 在我的操作中添加了文本。输出如下所示:

 FAIL  src/App.snapshot.test.js
  ● app container › dispatches correct actions upon rendering

    expect(value).toMatchSnapshot()

    Received value does not match stored snapshot 1.

    - Snapshot
    + Received

    -"function (dispatch) {
    -    return _axios2.default.get(endpoint).
    -    then(response => {
    -      return dispatch({
    -        type: _ActionTypes.GET_WEATHER_DONE,
    -        payload: response.data });
    +"function (dispatch) {/* istanbul ignore next */cov_2rypo7bhf.f[1]++;cov_2rypo7bhf.s[2]++;
    +    return (/* istanbul ignore next */_axios2.default.get(endpoint).
    +      then(response => {/* istanbul ignore next */cov_2rypo7bhf.f[2]++;cov_2rypo7bhf.s[3]++;
    +        return dispatch({
    +          type: /* istanbul ignore next */_ActionTypes.GET_WEATHER_DONE,
    +          payload: response.data });

    -    }).
    -    catch(error => {
    -      return dispatch({
    -        type: _ActionTypes.GET_WEATHER_ERROR,
    -        payload: error.response.data,
    -        statuscode: error.response.status });
    +      }).
    +      catch(error => {/* istanbul ignore next */cov_2rypo7bhf.f[3]++;cov_2rypo7bhf.s[4]++;
    +        return dispatch({
    +          type: /* istanbul ignore next */_ActionTypes.GET_WEATHER_ERROR,
    +          payload: error.response.data,
    +          statuscode: error.response.status });

    -    });
    +      }));
       }"

      at Object.it (src/App.snapshot.test.js:21:18)
      at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)

我面临的主要问题是我需要调用toString方法进行比较。在 Jest 测试中比较(匿名)函数的正确方法是什么?

完整源代码可在 https://github.com/wvanvlaenderen/react-redux-weathercomponent 找到

最佳答案

当使用 Jest 测试 redux thunk 时,我使用了 expect.any(Function)。所有断言库都有类似的东西。

例如)

行动

const toggleFilter = (toggle, isShown) => {
  return dispatch => {
    toggle === 'TOGGLE ONE'
      ? dispatch(toggleSwitchOne(isShown))
      : dispatch(toggleSwitchTwo(isShown));
  };
};

测试文件:

beforeEach(() => {
store = mockStore({ showFruit: false, showVeg: false });
      dispatch = jest.fn();
      getState = () => store;
})

it('will dispatch action to toggle switch', () => {
  let res = toggleFilter(type, isShown)(dispatch, getState);
  expect(dispatch).toHaveBeenCalledTimes(1);
  expect(dispatch).toHaveBeenCalledWith(expect.any(Function));
});

关于javascript - 如何在 Jest 测试中比较(匿名)函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46368672/

相关文章:

node.js - Redux 状态属性未定义且 ComponentDidMount 未触发

php - 在 React 中为服务器端渲染生成 CSS - Material-UI

javascript - React-redux 递归渲染组件时未获取状态

php - responseText 没有显示任何内容

javascript - 允许输入类型中的数字范围 - plunker

javascript - 添加绝对定位元素导致换行

javascript - Recurly.js 和 Angular 4

javascript - create-react-app 使用自定义 Service Worker 而不弹出

css - 覆盖样式组件中子样式的最佳方法

javascript - 是否有标准方法来路由 setState redux 操作?