Шут ожидается, макет не называется (избыточный компонент) - PullRequest
0 голосов
/ 09 июля 2019

В React я тестирую, что нажатие кнопки внутри дочернего компонента вызывает функцию, вызываемую в родительском компоненте (onDeleteClick), через всплывающее событие. Для этого теста я использую mount, так как мелкий не позволит нам запускать функцию в дочернем компоненте.

onDeleteClick, функция, которую я пытаюсь проверить, была ли она вызвана или нет, является свойством класса, которое в данном случае является функцией стрелки.

Я прикалываюсь над функцией onDeleteClick и передаю ее в свой компонент через Redux Provider при запуске теста.

Проблема, с которой я сталкиваюсь, заключается в том, что в конце теста, когда я выполняю проверку, чтобы проверить, была ли вызвана смоделированная функция, она возвращает 0.

expect(onDeleteClick.mock.calls.length).toBe(1);

Если я поместил console.log в onDeleteClick (), он будет выведен во время теста, поэтому я знаю, что функция на самом деле вызывается.

Я немного исследовал это и до сих пор не получил ничего, чтобы работать. Некоторые предложения заключались в том, чтобы шпионить за моей поддельной функцией, а затем вызвать forceUpdate для оболочки, но это не дало никаких положительных результатов.

Для этого я использую Jest с Enzyme.

Ссылочный код:

Parent.js

    import { deleteAccount } from '../../actions/profileActions';
    import ChildComponent from '../common/ChildComponent';

    class ParentComponent extends Component {

      onDeleteClick = () => {
        console.log('onDeleteClick was executed during this test!')
        this.props.deleteAccount();
      }

      render() {
        let dashboardContent;

        dashboardContent = (
           <div>
              <ChildComponent onDelete={this.onDeleteClick} />
           </div>
        );

        return (
          <div>
             {dashboardContent}
          </div>
        );
      }
    }

    // propTypes and mapStateToProps removed from this post

    export default connect(
      mapStateToProps,
      { deleteAccount }
    )(ParentComponent);

__ испытания __ / ParentComponent.js


    import React from 'react';
    import { mount } from 'enzyme';
    import { BrowserRouter as Router } from 'react-router-dom';
    import { Provider } from 'react-redux';    
    import configureStore from 'redux-mock-store';
    import ParentComponent from '../ParentComponent';
    import thunk from "redux-thunk";    
    const mockStore = configureStore([thunk]);

    const deleteAccount = jest.fn();

    const props = {
      deleteAccount
    }

    const randomTestState = {
    // some initial state, not important
    };

    const randomTestStore = mockStore(randomTestState);

    describe('<ParentComponent />', () => {
      it(`mounts the ParentComponent component and, when ChildComponent sends onDelete, then deleteAccount function is called once`, () => {

        const wrapper = mount(
          <Provider store={randomTestStore} props={props}>
            <Router >
              <ParentComponent />
            </Router>
          </Provider>
        );

        // Here, I grab an element in ChildComponent and simulate a click using Enzyme, then the event bubbles up, and deleteAccount() is called in the parent component. 

        // the console.log we expect to see from onDeleteClick is logged to console.
        // the call does not seem to have registered though and the expect returns falsy

        expect(deleteAccount.mock.calls.length).toBe(1);
      })

    });

Может быть проблема в том, что я обертываю компонент в провайдере? У меня есть предчувствие, но я не смог найти конкретных примеров тестов, которые используют провайдера для переноса их компонента при выполнении интеграционного тестирования

1 Ответ

0 голосов
/ 24 июля 2019

Решение состояло в том, что мне нужно было изменить мой основной файл ParentComponent с

class ParentComponent extends Component {

к этому:

extend class ParentComponent extends Component {

и затем в моем тестовом файле импортируйте компонент следующим образом:

import { ParentComponent } from '../ParentComponent'; // non-default export should be wrapped in braces

и затем обновите мой тест, чтобы я назначил переменную-обертку следующим образом:

const wrapper = mount(<ParentComponent {...props} />);

Это позволило тесту пройти

expect(deleteAccount.mock.calls.length).toBe(1);

Было рекомендовано здесь, в документации Redux

...