简体   繁体   English

如何在玩笑测试中比较(匿名)功能?

[英]How to compare (anonymous) function in jest tests?

I am having the following React component connected to a redux store.我将以下 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)

This component is dispatching the getWeather action using the componentDidMount callback.此组件使用componentDidMount回调分派getWeather操作。 The getWeather action is returning an anonymous method upon resolving the axios promise. getWeather操作在解析 axios 承诺时返回一个匿名方法。

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
      })
    })
  }
}

No I am trying to write a unit test verifying the getWeather action is being dispatched upon mounting.不,我正在尝试编写一个单元测试来验证getWeather操作是否在安装时被分派。 This tests looks as follows and passes.该测试如下所示并通过。

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())
  })

})

Because of the action returning an anonymous method, I need to call the toString method upon my mock to compare the actions.由于操作返回匿名方法,我需要在模拟上调用toString方法来比较操作。

I recreated this test using snapshot testing.我使用快照测试重新创建了这个测试。

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();
  })


})

Again I need to call the toString method, resulting in the following snapshot.我再次需要调用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 });

    });
  }"
`;

Now when running coverage, using the yarn test -- --coverage , my test is failing because of istanbul adding text to my action.现在,当运行覆盖率时,使用纱线测试 -- --coverage ,我的测试失败了,因为 istanbul 在我的操作中添加了文本。 The output looks as follows:输出如下所示:

 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)

The main problem I am facing is the fact that I need to call the toString method for comparison.我面临的主要问题是我需要调用toString方法进行比较。 What is the correct method for comparing (anonymous) functions in jest testing?在玩笑测试中比较(匿名)函数的正确方法是什么?

Full source can be found at https://github.com/wvanvlaenderen/react-redux-weathercomponent完整源代码可以在https://github.com/wvanvlaenderen/react-redux-weathercomponent找到

So I was able test calls on dispatch by mocking the getWeather action in my test, and verifying the type of the return value on individual calls.因此,我能够通过在我的测试中模拟 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'
import { spy } from 'sinon'

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

  const dispatchSpy = spy(store, 'dispatch')

  actions.getWeather = jest.fn().mockImplementation(() => {
    return {type: 'fetching weather'}
  })

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

    expect(dispatchSpy.firstCall.returnValue.type).toEqual('fetching weather')
  })

})

Snapshot testing was achieved by rendering the call tree on the dispatch spy.快照测试是通过在调度间谍上渲染调用树来实现的。

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { spy } from 'sinon'
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 = spy(store, 'dispatch')

  actions.getWeather = jest.fn().mockImplementation(() => {
    return {type: 'fetching weather'}
  })

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

    expect(dispatchSpy.getCalls()).toMatchSnapshot();
  })

})

When testing a redux thunk using Jest, i've used expect.any(Function) .使用 Jest 测试 redux thunk 时,我使用了expect.any(Function) All assertion libs have something like this.所有断言库都有这样的东西。

ex)例如)

action行动

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

Test file:测试文件:

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));
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM