Тестирование реакции - как я могу имитировать или вводить данные в магазин, которые будут предоставлены в качестве реквизита для компонента

Я использую jest и react-testing-library, чтобы обеспечить покрытие моего приложения модульными тестами.

Я использую эту удобную вспомогательную функцию, которую Кент С. Доддс показал в одном из своих видеороликов:

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. Я хочу иметь возможность по крайней мере имитировать передаваемые данные, но мне не удалось использовать реквизиты, так как хранилище имеет приоритет.

Надеюсь, что кто-нибудь сможет пролить свет на помощь или поделиться советом. Заранее спасибо!


person aromanarguello    schedule 26.03.2019    source источник
comment
Первое, что следует учитывать - объект, который вы передаете в NavBar через props, не предоставляет необходимые ему свойства. Например, NavBar ожидает, что атрибут isReady, но вы передаете его как атрибут другого объекта, component = {isReady}   -  person leosteffen    schedule 27.03.2019
comment
: / это на самом деле не решает мою проблему, похоже, что эти реквизиты ничего не делают. Поскольку Navbar подключен к хранилищу redux, он по приоритету получает реквизиты хранилища, и эти реквизиты являются пустыми массивами до тех пор, пока они не будут извлечены. Мне это нужно, чтобы взять фиктивные данные для тестирования. Надеюсь, это имеет смысл @leosteffen   -  person aromanarguello    schedule 27.03.2019
comment
Я не лучший человек, чтобы помочь с особенностями redux, но я бы 1) тестировал компонент изолированно, а не подключался к redux и 2) тестировал функцию fetchTickets () самостоятельно. Таким образом, вы можете убедиться, что ваши отдельные части работают должным образом, пока вы не узнаете, нужно ли / как тестировать их вместе.   -  person leosteffen    schedule 27.03.2019
comment
В этом есть смысл. Я тестировал каждый отдельно. Я тестирую свои действия с redux-mock-stor и редукторами отдельно .. Думаю, я хотел смоделировать и протестировать сквозной опыт работы с компонентом lol   -  person aromanarguello    schedule 27.03.2019
comment
Ясно, просто убедитесь, что вы не закончили тестировать redux: P   -  person leosteffen    schedule 27.03.2019


Ответы (2)


Я создал вспомогательную функцию, чтобы обернуть мои компоненты 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})
person Alexandr Zavalii    schedule 26.03.2019

Официальный документ Writing Tests от Redux рекомендует этот подход:

Но иногда вы хотите протестировать только рендеринг компонента без хранилища Redux.

Чтобы иметь возможность протестировать сам компонент ... без необходимости иметь дело с декоратором, мы рекомендуем вам также экспортировать недекорированный компонент.

Другими словами ... экспортируйте NavBar как именованный экспорт, чтобы вы могли получить к нему доступ в своих тестах.

Затем вы можете протестировать его напрямую как простой компонент пользовательского интерфейса, который просто отрисовывается на основе props, которые вы ему даете.

person Brian Adams    schedule 27.03.2019
comment
Это тоже имеет смысл! Спасибо, что поделился :) - person aromanarguello; 27.03.2019
comment
если вы import { Component } from "./Component";, вам не нужно будет оборачивать store / provider. - person Phil Lucks; 15.10.2019