Как проверить mapStateToProps, используя React Redux и Jest? - PullRequest
1 голос
/ 16 января 2020

Когда я создаю тест для моего подключенного компонента React, в котором я хочу проверить logStateToProps logi c Я сталкиваюсь с проблемой, которую не знаю, как ее решить.

Сообщение об ошибке

Expected: 1
Received: undefined

  24 |     it('should show previously rolled value', () => {
  25 |         // test that the state values were correctly passed as props
> 26 |         expect(wrapper.props().lastRolledNumber).toBe(1);

Когда я проверяю wrapper.props (), он возвращает только объект хранилища и никаких свойств.

Чтобы убедиться, что это не мой код, я нашел пример, который должен работать, чтобы упростить его, но я получаю ту же проблему при использовании этой точной версии в моем приложении (опция # 2, https://jsramblings.com/2018/01/15/3-ways-to-test-mapStateToProps-and-mapDispatchToProps.html)

Я думаю, что это может иметь отношение к версии React 16+, которая Я нашел здесь упомянутое: https://airbnb.io/enzyme/docs/api/ReactWrapper/props.html

.props () => Object

Возвращает объект props для узла root оболочки. Это должна быть одноузловая оболочка. Этот метод является надежным способом доступа к подпоркам узла; Также будет работать propper wrapper.instance (). props, но в React 16+ функциональные компоненты без состояния не имеют экземпляра. См. .Instance () => ReactComponent

Кто-нибудь знает, как проверить это хорошим способом, чтобы убедиться, что logi c работает должным образом без непосредственного экспорта частной функции mapStateToProps?

Компонент

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

// Component 1 - "Base component"
// Exporting it is a good practice for testing its own logic
export const Dice = ({ lastRolledNumber, onRollDice }) => (
    <div>        
        <p>The last rolled number was {lastRolledNumber}.</p>
        <button onClick={onRollDice}>Roll dice</button>
    </div>
);

Dice.propTypes = {
    lastRolledNumber: PropTypes.number.isRequired,
    onRollDice: PropTypes.func.isRequired
}

const mapStateToProps = (state) => ({
    lastRolledNumber: state.lastRolledNumber
});

const mapDispatchToProps = (dispatch) => ({
    onRollDice: () => dispatch({ type: 'ROLL_DICE' })
});

// Component 2 - Container component
// Export it as a default export
export default connect(mapStateToProps, mapDispatchToProps)(Dice);

Тест

import React from 'react';
import { shallow } from 'enzyme';
import '../test-config'; // Setup Enzyme & Adapter

import DiceContainer from './Dice';

// Create the mock store
import configureMockStore from 'redux-mock-store';
const mockStore = configureMockStore();

describe('Dice', () => {
    let wrapper, store;

    beforeEach(() => {
        const initialState = {
            lastRolledNumber: 1
        };
        store = mockStore(initialState);
        // Shallow render the container passing in the mock store
        wrapper = shallow(
            <DiceContainer store={store} />
        );
    });

    it('should show previously rolled value', () => {
        // test that the state values were correctly passed as props
        expect(wrapper.props().lastRolledNumber).toBe(1);
    });

    it('should roll the dice again when button is clicked', () => {
        // test that the component events dispatch the expected actions 
        wrapper.simulate('rollDice');

        const actions = store.getActions();
        expect(actions).toEqual([ { type: 'ROLL_DICE' } ]);
    });
});

1 Ответ

1 голос
/ 16 января 2020

Вы почти у цели. Вам нужно вызвать метод .dive () , чтобы получить компонент Dice вместо компонента DiceContainer, который обернут модулем connect HO C из react-redux.

Краткий ответ:

wrapper = shallow(<DiceContainer store={store} />).dive();

A Завершенный рабочий пример:

index.jsx:

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

export const Dice = ({ lastRolledNumber, onRollDice }) => (
  <div>
    <p>The last rolled number was {lastRolledNumber}.</p>
    <button onClick={onRollDice}>Roll dice</button>
  </div>
);

Dice.propTypes = {
  lastRolledNumber: PropTypes.number.isRequired,
  onRollDice: PropTypes.func.isRequired,
};

const mapStateToProps = (state) => ({
  lastRolledNumber: state.lastRolledNumber,
});

const mapDispatchToProps = (dispatch) => ({
  onRollDice: () => dispatch({ type: 'ROLL_DICE' }),
});

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

index.test.jsx:

import React from 'react';
import { shallow } from 'enzyme';
import configureMockStore from 'redux-mock-store';
import DiceContainer from '.';

const mockStore = configureMockStore();

describe('Dice', () => {
  let wrapper;
  let store;

  beforeEach(() => {
    const initialState = {
      lastRolledNumber: 1,
    };
    store = mockStore(initialState);
    wrapper = shallow(<DiceContainer store={store} />).dive();
  });

  it('should show previously rolled value', () => {
    expect(wrapper.props().lastRolledNumber).toBe(1);
  });

  it('should roll the dice again when button is clicked', () => {
    wrapper.simulate('rollDice');
    const actions = store.getActions();
    expect(actions).toEqual([{ type: 'ROLL_DICE' }]);
  });
});

Результаты юнит-теста:

 PASS  src/stackoverflow/59771991/index.test.jsx (9.645s)
  Dice
    ✓ should show previously rolled value (19ms)
    ✓ should roll the dice again when button is clicked (2ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        11.505s

Тестовое покрытие html Отчет:

enter image description here

...