使用 Jest 和 Redux 的异步组件快照

2024-04-04

我发现 Jest 在测试我的 Redux React 应用程序时非常有用。然而,有很多关于如何测试异步操作创建器的示例,但我无法真正弄清楚如何对异步组件进行快照。

我想做的是类似的事情Facebook 自己的教程中的悬停链接示例 https://facebook.github.io/jest/docs/tutorial-react.html#snapshot-testing。他们调用 props 函数 onMouseEnter() 并随后拍摄快照。如果 onMouseEnter() 调度使用 Redux Thunk 创建的异步操作,是否有一种简单的方法可以做到这一点?

这就是我的 thunk 的样子,它使用 axios。

  // test-api.js

  export function getLinkInfo() {
  return function(dispatch) {
    return axios.get('/api/get-link-info')
    .then(response => {
        dispatch(getLinkInfoSuccess(response.data));
        return response;
    });
  };
}

这是我自己的 Link 组件。

import React from 'react';
import { connect } from 'react-redux';
import * as api from '../../api/test-api';

class Link extends React.Component {
  render() {
    return (
      <a href='#' onMouseEnter={this.props.getLinkInfo}>
        Hover me
      </a>
      <div>{this.props.linkInfo}</div>
    );
  }
}

const mapDispatchToProps = function(dispatch) {
  return {
    getLinkInfo: function() {
      dispatch(api.getLinkInfo());
    }
  }
}

const mapStateToProps = function(store) {
  return {
    linkInfo: store.getIn(['testState', 'linkInfo'], "")
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Link);

最后是测试文件。

import React from 'react';
import Link from '../link';
import renderer from 'react-test-renderer';

test('Link changes linkInfo when hovered', () => {
  const component = renderer.create(
    <Link></Link>
  );
  let tree = component.toJSON();
  expect(tree).toMatchSnapshot();

  // manually trigger the callback
  tree.props.onMouseEnter();
  // re-rendering
  tree = component.toJSON();
  expect(tree).toMatchSnapshot();
});

问题是,当您想测试异步内容时,您需要在测试中使用 Promise 的实例,要么从测试返回它,这样笑话就知道它并可以等待它,要么在测试中使用 async wait(docs) https://facebook.github.io/jest/docs/asynchronous.html#content.

你可以做的是在测试中模拟 api:

从 'path/to/the/api' 导入 {getLinkInfo} jest.mock('path/to/the/api', () = > ({ 获取链接信息:jest.fn() }))

这将使用具有间谍功能的对象覆盖该模块getLinkInfo。然后导入该模块,以便您可以在测试中设置间谍的实际实现。

test('Link changes linkInfo when hovered', () = > {
  //create a new promise that can be returned from your test
  const p = new Promise((resolve) = > {
    //set the spy to make the request and resolve the promise
    getInfo.mockImplementation(function (dispatch) {
      return axios.get('/api/get-link-info')
        .then(response = > {
          dispatch(getLinkInfoSuccess(response.data));
          resolve(response);
        });
    };)
  };)
  const component = renderer.create(
    <Link></Link>
  );
  let tree = component.toJSON();
  expect(tree)
    .toMatchSnapshot();
  // manually trigger the callback
  tree.props.onMouseEnter();
  return p.then(() = > {
    tree = component.toJSON();
    expect(tree)
      .toMatchSnapshot()
  })
});

虽然这可能会解决您的实际问题,但我建议不要像这样运行您的测试,调用您的真实 API,但也要模拟请求本身。首先,您的测试会快得多,并且它不依赖于某些正在运行的后端。

关键是你想将你的 React 组件作为一个单元进行测试,所以它不关心调用后发生了什么getLinkInfo。这些是单元测试的详细信息getLinkInfo。您的组件所知道的就是,它调用getLinkInfo传入一个回调,这个回调有时会被调用。当它被调用时以及其间发生的事情不属于组件的责任范围。如果您考虑这样的测试,最简单的解决方案是立即调用回调。

test('Link changes linkInfo when hovered', () = > {
  getInfo.mockImplementation(function (dispatch) {
    dispatch({
      some: 'Data'
    });
  };)
  const component = renderer.create(
    <Link></Link>
  );
  let tree = component.toJSON();
  expect(tree)
    .toMatchSnapshot();
  // manually trigger the callback
  tree.props.onMouseEnter();
  tree = component.toJSON();
  expect(tree).toMatchSnapshot()
});
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Jest 和 Redux 的异步组件快照 的相关文章

随机推荐