【问题标题】:Testing a connected functional component without an action dispatching在没有动作调度的情况下测试连接的功能组件
【发布时间】:2020-04-02 04:36:48
【问题描述】:

我有一个连接的组件,它从 Redux 存储中获取数据,所以基本上该组件呈现数据,没有要调度的操作。我正在使用 antd 来渲染表格,以便设置 垂直高度我正在计算高度并传递给参考。我也在为这个示例应用程序使用样式化组件。

如何使用 Jest 和 Enzyme 进行测试。大多数文章和资源都显示了调度按钮操作和获取数据。

查看下面的组件

table.js

import React, { useState, useEffect, useRef, useLayoutEffect } from "react";
import { Table, Alert, Icon } from "antd";
import { connect } from "react-redux";

import constants from "../constants";
import helpers from "../helpers";
import Style from "./style";
import hooks from "../hooks";
import Icon from "../DisabledIcon";

const {
    column_headings: { top_view, front_view },
    unique_keys: { TOP_VIEW },
} = constants;
const { transformRowData } = helpers;

const { TableContainer } = Style;

const { useWindowSize } = hooks;

const Table = props => {
    const {
        isTableDataLoading,
        tableData,
        selectedView,
        headerHeight,
        isTableError,
        tableErrorMessage,
    } = props;
    const [formattedTableData, setFormattedTableData] = useState([]);
    const [columnHeadings, setColumnHeadings] = useState([]);

    const tableRef = useRef(null);
    const size = useWindowSize();
    const [tableHeight, setTableHeight] = useState(118);

    useEffect(() => {
        if (tableData && tableRef.current) {
            let tableHead = document.querySelector(
                `.${tableRef.current.classList[0]} table > thead`
            );
            const reducedPixel = tableHead.offsetHeight + headerHeight;
            setTableHeight(reducedPixel);
        }
    }, [size, tableData, headerHeight]);

    useEffect(() => {
        if (tableData) {
            let columnTitlesList = selectedView === TOP_VIEW ? top_view : front_view;
            columnTitlesList = columnTitlesList.map(colTitle => {
                if (colTitle.key === "disabled") {
                    return {
                        ...colTitle,
                        render: (text, data) => {
                            return <Icon component={text && Icon} />;
                        },
                    };
                }
                return colTitle;
            });
            setColumnHeadings(columnTitlesList);
            const transformedTableData = transformRowData(tableData.list, columnTitlesList);
            setFormattedTableData(transformedTableData);
        }
    }, [tableData]);

    return (
        <>
            {isTableError ? (
                <Alert
                    message={<p style={{ textAlign: "center" }}>{tableErrorMessage}</p>}
                    type="error"
                />
            ) : (
                <TableContainer ref={tableRef}>
                    <Table
                        columns={columnHeadings}
                        rowClassName={record => !record.isEnabled && "disabled-row"}
                        dataSource={formattedTableData}
                        pagination={false}
                        scroll={{ y: `calc(100vh - ${tableHeight}px)` }}
                        loading={isTableDataLoading}
                    />
                </TableContainer>
            )}
        </>
    );
};

const mapStateToProps = ({ tableState }) => {
    return {
        isTableDataLoading: tableState.isLoading,
        isTableError: tableState.isError,
        tableErrorMessage: tableState.errorMessage,
        tableData: tableState.payload,
        selectedView: tableState.view,
    };
};

export default connect(mapStateToProps, null)(Table);

我已经尝试编写基本测试,也是在 configureStore 中,我是否应该通过中间件,因为我使用的是 Redux Thunk。

table.test.js

import React from "react";
import { shallow } from "enzyme";
import configureStore from "redux-mock-store";
import constants from "../constants";
import Table from "../Table";
import { Provider } from "react-redux";

const mockStore = configureStore([]);
const {
    unique_keys: { TOP_VIEW },
} = constants;

describe("Table", () => {
    let store;
    let component;
    beforeEach(() => {
        store = mockStore({
            isLoading: false,
            isError: false,
            errorMessage: null,
            payload: null,
            selectedView: TOP_VIEW,
        });
        component = shallow(
            <Provider store={store}>
                <Table />
            </Provider>
        );
    });

    it("should render the component", () => {
        expect(component).toMatchSnapshot();
    });
});

【问题讨论】:

    标签: reactjs jestjs enzyme


    【解决方案1】:

    通常通过导出组件的未连接版本并为其编写测试来测试连接的组件。这使您可以控制将哪些数据以及何时提供给组件和模拟操作。而且您不需要模拟商店。有关示例,请参见 Redux docs

    但是,请注意,使用 shallow rendering 时,带有钩子的组件更难测试。

    【讨论】:

    • 感谢您的回复,问题是当我导出组件时会抛出错误,这就是为什么我也提到了测试用例文件。有什么方法可以测试这个。如果您发现该问题需要答案,请点赞
    • 导出未连接的组件会抛出什么样的错误?
    • @DILEEPTHOMAS 你能找到一种方法来使用 useState() 钩子测试你连接的组件吗?如果是这样,你能在这里分享 test.js 文件吗?谢谢!
    猜你喜欢
    • 2021-03-31
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 2021-10-11
    • 2019-05-12
    • 2014-11-17
    • 1970-01-01
    • 2012-07-12
    相关资源
    最近更新 更多