【问题标题】:How to generate snapshot after all life cycle methods have called in React Jest在 React Jest 中调用所有生命周期方法后如何生成快照
【发布时间】:2017-08-13 10:05:12
【问题描述】:

在调用componentDidMount() 之前已创建快照文件。在我的情况下,我从componentDidMount() 内的服务器获取数据。根据结果​​,我绘制了表格。但在我的测试用例中,它没有显示那些收到的模拟结果

测试文件

import React from 'react';
import renderer from 'react-test-renderer';
import { fakeRequestLibrary } from '../../../__mocks__/fakeRequestLibrary';
import ReportAsTableView from '../../../components/reports/common/ReportAsTableView';

const FAKE_RESPONSE = {
    dataSets: [
        {
            metadata: {
                columns: [
                    {
                        name: "username",
                        label: "username"
                    },
                    {
                        name: "date_created",
                        label: "date_created"
                    }
                ]
            },
            rows: [
                {
                    date_created: "2010-04-26T13:25:00.000+0530",
                    username: "daemon"
                },
                {
                    date_created: "2017-06-08T21:37:18.000+0530",
                    username: "clerk"
                },
                {
                    date_created: "2017-07-08T21:37:18.000+0530",
                    username: "nurse"
                },
                {
                    date_created: "2017-07-08T21:37:19.000+0530",
                    username: "doctor"
                },
                {
                    date_created: "2017-07-08T21:37:18.000+0530",
                    username: "sysadmin"
                }
            ]
        }
    ]

};

describe('<ReportAsTableView /> ', () => {
    it('renders correctly with success data received from server', () => {
        const params = {
            "startDate": "2017-05-05",
            "endDate": "2017-10-05"
        };


        var rendered = renderer.create(
            <ReportAsTableView reportUUID="e451ae04-4881-11e7-a919-92ebcb67fe33"
                reportParameters={params}
                fetchData={fakeRequestLibrary('openmrs-fake-server.org', {}, true, FAKE_RESPONSE)} />
        );

        expect(rendered.toJSON()).toMatchSnapshot();
    });
});

有针对性的组件类

import React, { Component } from 'react';
import { ApiHelper } from '../../../helpers/apiHelper';
import * as ReportConstants from '../../../helpers/ReportConstants';
import ReactDataGrid from 'react-data-grid';
import DataNotFound from './DataNotFound';
import moment from 'moment';
import './ReportAsTableView.css';


class ReportAsTableView extends Component {

    constructor(props) {
        super();
        this.state = {
            report: {
                definition: {
                    name: ''
                }
            },
            reportColumnNames: Array(),
            reportRowData: Array()
        };
        this.resolveResponse = this.resolveResponse.bind(this);
        this.rowGetter = this.rowGetter.bind(this);
        this.init = this.init.bind(this);
    }

    componentDidMount() {
        this.init(this.props.reportParameters);
    }

    componentWillReceiveProps(nextProps) {
        this.init(nextProps.reportParameters);
    }

    init(params) {

        if(this.props.fetchData != null){
            //Test Path
            this.props.fetchData
            .then((response) => {
                console.log('>>>>>'+JSON.stringify(response.body));
                this.resolveResponse(response.body);
            });
        }else{
            new ApiHelper().post(ReportConstants.REPORT_REQUEST + this.props.reportUUID, params)
            .then((response) => {
                this.resolveResponse(response);
            });
        }
    }

    resolveResponse(data) {
        this.setState({ report: data });
        this.setState({ reportColumnNames: data.dataSets[0].metadata.columns });
        this.setState({ reportRowData: data.dataSets[0].rows });
    }

    // ... there are some other methods as well


    render() {
        return (
            <div style={{ border: '1px solid black' }}>

                {this.getColumns().length > 0 ? (

                    <ReactDataGrid
                        columns={this.getColumns()}
                        rowGetter={this.rowGetter}
                        rowsCount={this.state.reportRowData.length} />
                ) : (
                    <DataNotFound componentName="Report Table"/>
                )}

            </div>
        );
    }

}

export default ReportAsTableView;

快照文件

// Jest Snapshot v1,

exports[`<ReportAsTableView />  renders correctly with success data received from server 1`] = `
<div
  style={
    Object {
      "border": "1px solid black",
    }
  }
>
  <div
    className="NotFoundWrapper"
  >
    <div
      className="attentionSign"
    >
      <img
        src="./warning.png"
        width="300"
      />
    </div>
    <div>
      No Data found 
      <span>
        for 
        Report Table
      </span>
    </div>
  </div>
</div>
`;

更新:

fakeRequestLibrary

​​>
import Response from 'http-response-object';

export const fakeRequestLibrary = (requestUrl, requestOptions, shouldPass = true, responseData = null) => {
  return new Promise((resolve, reject) => {
    if (shouldPass) {
      resolve(new Response(200, {}, responseData || { message: `You called ${requestUrl}` }, requestUrl));
    } else {
      reject(new Response(404, {}, responseData || { message: `The page at  ${requestUrl} was not found` }, requestUrl));
    }
  });
};

【问题讨论】:

  • 你能把fakeRequestLibrary的代码贴出来吗?
  • @GabrielDiez 我也添加了 fakeRequestLibrary :)
  • 我认为你有这个问题,因为 fakeRequestLibrary 是异步的。您应该尝试将虚假数据传递给您的组件,然后渲染它们,而不是尝试重现 API 调用。不要忘记您正在测试渲染而不是整个组件
  • 这是我的项目。你能构造一个答案吗? Repository
  • this.props.fetchData 应该是什么?之前提取的数据?

标签: reactjs unit-testing react-native jestjs


【解决方案1】:

除了传递一个 http 端点,你可以做的是改变你的 init 方法并在没有数据传递的情况下传递数据来获取它们。像这样

init(params) {

    if(this.props.fetchData != null){
            this.resolveResponse(this.props.fetchData);
    }else{
        new ApiHelper().post(ReportConstants.REPORT_REQUEST + this.props.reportUUID, params)
        .then((response) => {
            this.resolveResponse(response);
        });
    }
}

那么在你的测试中你将拥有

    var rendered = renderer.create(
        <ReportAsTableView reportUUID="e451ae04-4881-11e7-a919-92ebcb67fe33"
            reportParameters={params}
            fetchData={FAKE_RESPONSE} />
    );

    expect(rendered.toJSON()).toMatchSnapshot();

【讨论】:

    【解决方案2】:

    此解决方案适用于我自己的项目。它也可能适用于这个问题,但我还没有测试过。添加await wait();语句等待componentDidMount中的异步函数完成。

    const wait = async () => 'foo'; // a dummy function to simulate waiting
    
    describe('<ReportAsTableView /> ', async () => {
      it('renders correctly with success data received from server', async () => {
        const params = {
          startDate: '2017-05-05',
          endDate: '2017-10-05',
        };
    
        var rendered = renderer.create(
          <ReportAsTableView
            reportUUID="e451ae04-4881-11e7-a919-92ebcb67fe33"
            reportParameters={params}
            fetchData={fakeRequestLibrary(
              'openmrs-fake-server.org',
              {},
              true,
              FAKE_RESPONSE,
            )}
          />,
        );
    
        await wait(); // wait for <ReportAsTableView> to finish async data fetch in componentDidMount()
    
        expect(rendered.toJSON()).toMatchSnapshot(); // shall render the component AFTER componentDidMount() is called
      });
    });
    
    

    【讨论】:

      【解决方案3】:

      试试这个:

       import { mount } from 'enzyme';
      
      const wrapper = mount(<MyComponent />);
      expect(toJson(wrapper)).toMatchSnapshot();
      

      【讨论】:

      • 欢迎来到 SO。请为您的答案添加一些解释。 enzyme 是什么?这如何解决 OP 的问题?
      猜你喜欢
      • 2012-11-22
      • 1970-01-01
      • 1970-01-01
      • 2017-05-18
      • 2017-08-28
      • 1970-01-01
      • 1970-01-01
      • 2020-09-19
      • 1970-01-01
      相关资源
      最近更新 更多