React 测试 - 如何在商店中模拟或注入数据以作为道具提供给组件

React testing - How can I mock or inject data in the store to be provided as props to component

我正在使用 jest 和 react-testing-library 为我的应用程序提供单元测试覆盖率。

我使用这个方便的辅助函数 Kent C. Dodds 在他的一个视频中展示过:

const renderWithRedux = ui => ({
    ...render(<Provider store={store}>{ui}</Provider>),
    store,
});

我在测试连接组件时使用。

我 运行 遇到一个问题,为了呈现一个组件,我需要获取一些数据来准确地解决测试,或者至少将模拟数据注入商店。我没有这样做

这是我的测试:

test('navbar accepts props', async () => {
    /**
     * Something I was testing
     */
    const functionToTest = () => async dispatch => {
        dispatch(fetchTickets());
    };

    functionToTest();
    const isReady = true;
    const mockData = {
        sessionInformation: {
            ticket: { label: 'Total Tickets' },
            sessionDuration: { sessionLabel: 'Session Duration', duration: 42 },
            equipment: { type: 'Desktop', operatingSystem: 'Windows' },
        },
        component: { isReady },
        tickets: {
            ticketPayload: [
                {
                    number: '1020312039',
                    shortDescription: 'Accessories',
                    status: 'Active',
                    createdOnEpoch: 1512322200000,
                },
            ],
        },
    };

    const data = renderWithRedux(<Navbar props={mockData} />);
});

我正在测试的组件:

const NavBar = ({
    openTickets: { label },
    sessionDuration: { sessionLabel, duration },
    tickets: { ticketPayload = [] },
    isReady,
}) => (!isReady ? (
    <Container>
        <LogoContainer>
            <Logo src={logo} alt="logo" />
            <Header>Service Desk</Header>
        </LogoContainer>

        <SessionInformation className="session">
            <NavbarInfo className="session-info">
                <p>
                    <FontAwesomeIcon icon="ticket-alt" className="ticketIcon" />
                    {label}
                </p>
                <p>{`${ticketPayload.length} tickets`}</p>
            </NavbarInfo>
            <NavbarInfo last className="session-info">
                <p>
                    <FontAwesomeIcon icon="clock" className="ticketIcon" />
                    {sessionLabel}
                </p>
                <p>{`${duration} minutes`}</p>
            </NavbarInfo>
            {hasTokens() && (
                <Button type="submit" onClick={() => console.log('notes')}>
                        Notepad
                </Button>
            )}
        </SessionInformation>
    </Container>
) : (
    <LoaderContainer>
        <RingLoader size={100} />
    </LoaderContainer>
));

我需要用 ticketPayload 进行长度计算,但主要商店优先。由于尚未获取该信息,因此 ticketPayload 的值为 0。我希望能够至少模拟要传递的数据,但使用道具时运气不佳,因为商店优先。

希望任何人都能提供帮助或分享一些指导。提前致谢!

我创建了一个辅助函数来用 redux 包装我的组件。

import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import initialState from '../store/initialState';

const mockStore = (state = initialState) => configureMockStore()(state);

export const testableComponent = (component, state) =>
  (<Provider store={mockStore(state)}>{component}</Provider>);

然后你就可以像这样调用它,传递你的状态

testableComponent(<YourComponent />, {yourUpdatedMockedState})

来自 Redux 的官方 Writing Tests 文档推荐这种方法:

But sometimes you want to test just the rendering of the component, without a Redux store.

In order to be able to test the...component itself without having to deal with the decorator, we recommend you to also export the undecorated component

换句话说...将 NavBar 导出为 命名导出 ,以便您可以在测试中访问它。

然后您可以直接将其作为一个简单的 UI 组件进行测试,该组件仅根据您提供的 props 进行渲染。