Тестирование с помощью jest + энзима, фиктивные функции вызываются дважды без причины - PullRequest
0 голосов
/ 14 февраля 2019

Я пытаюсь выучить Jest и Enzyme, но у меня возникла проблема, я не могу найти решение, это мой тест ... я не очень хорошо знаю, но я учусь:

import * as apiMock from '../api';

const fakePostId = '1';
const fakePersona = 'Fake';

jest.mock('../api', () => {
    return {
        fetchAllComments: jest.fn(() => {
            return [];
        }),
        filterComments: jest.fn(() => {
            return [];
        }),
        createCommentObject: jest.fn(() => {
            return [];
        }),
    };
});

test('checks if functions are called after didMount', () => {
    const component = shallow(
        <Comments postId={fakePostId} currentPersona={fakePersona} />
    );

    const spySetComments = jest.spyOn(
        component.instance(),
        'setCommentsFromLocalStorage'
    );

    component.instance().componentDidMount();

    expect(spySetComments).toHaveBeenCalledTimes(1);

    //Don't know why these are called 2! times, I can't see why removing componentDidMount makes it 0.
    expect(apiMock.fetchAllComments).toHaveBeenCalledTimes(1);
    expect(apiMock.filterComments).toHaveBeenCalledTimes(1);
}

Проблема в toHaveBeenCalledTimes(1). Сбой по причине:

Ожидается, что фиктивная функция была вызвана один раз, но она была вызвана два раза.

Но я не знаю почему.setCommentsFromLocalStorage запускается только один раз, и эта функция должна запускаться из componentDidMount и выполнять эти вызовы API один раз.

ReactComponent looks like this:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import CreateNewComment from './CreateNewComment';
import SingleComment from './SingleComment';
import * as api from '../api';

class Comments extends Component {
  state = {
    comments: []
  };

  componentDidMount() {
    this.setCommentsFromLocalStorage();
  }

  setCommentsFromLocalStorage = (postId = this.props.postId) => {
    const fetchedComments = api.fetchAllComments();
    const comments = api.filterComments(fetchedComments, postId);
    this.setState({ comments });
  };

  removeComment = commentId => {
    api.removeComment(commentId);
    this.setCommentsFromLocalStorage();
  };

  renderCommentList = (comments, currentPersona) =>
    comments.map(comment => (
      <SingleComment
        {...comment}
        currentPersona={currentPersona}
        key={comment.id}
        onClick={this.removeComment}
      />
    ));

  render() {
    return (
      <div className="py-2">
        <h2 className="text-indigo-darker border-b mb-4">Comments</h2>
        {this.renderCommentList(this.state.comments, this.props.currentPersona)}
        <CreateNewComment
          postId={this.props.postId}
          author={this.props.currentPersona}
          updateComments={this.setCommentsFromLocalStorage}
        />
      </div>
    );
  }
}

Comments.propTypes = {
  postId: PropTypes.string.isRequired,
  currentPersona: PropTypes.string.isRequired
};

export default Comments;

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019

Используйте beforeEach и afterEach, чтобы издеваться и пересмеивать, соответственно, восстановить шпионов.

Это объясняется в разделе Настройка и Разрушение в Документах Jest.

0 голосов
/ 14 февраля 2019

componentDidMount вызывается во время shallow().


Это означает, что setCommentsFromLocalStorage вызывается, что вызывает fetchAllComments и filterComments все во время этого начального shallow() вызова.

api уже издевались, поэтому он записывает эти вызовы fetchAllComments и filterComments.


Как только это все произошло, шпион создаетсядля setCommentsFromLocalStorage и componentDidMount снова вызывается (который снова вызывает fetchAllComments и filterComments).

Шпион для setCommentsFromLocalStorage затем правильно сообщает, что он был вызван один раз(поскольку он существовал только во время второго вызова componentDidMount).

Шпионы fetchAllComments и filterComments затем правильно сообщают, что они были вызваны два раза , поскольку они существовали во время обоих вызовов - componentDidMount.


Самый простой способ исправить тест - очистить макеты на fetchAllComments и filterComments допозвоните по номеру componentDidMount:

apiMock.fetchAllComments.mockClear();  // clear the mock
apiMock.filterComments.mockClear();  // clear the mock

component.instance().componentDidMount();

expect(spySetComments).toHaveBeenCalledTimes(1);  // SUCCESS
expect(apiMock.fetchAllComments).toHaveBeenCalledTimes(1);  // SUCCESS
expect(apiMock.filterComments).toHaveBeenCalledTimes(1);  // SUCCESS
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...