Ошибка: ожидалось, что была вызвана фиктивная функция - энзим onclick Jest

Невозможно пройти следующий тест ... Извините за добавление большого количества кода ... Мне удалось получить некоторые другие события щелчка, но я застрял с этим в данный момент

Получение следующего сообщения:

"ожидать (jest.fn ()). toHaveBeenCalled ()

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

вот событие щелчка в методе рендеринга

      className={!this.state.name || !this.state.label || this.state.valueStore === null ? `add-custom-field-button disabled` : `add-custom-field-button`}
          id="test-addclick"
          onClick={() => {this.onAddClick()}}
        >
          Create Field
        </button>

вот метод onAddClick:

onAddClick = () => {
let obj = this.props.selectedFormJSON;

this.addValueAttribute().then(()=>{
  obj.FORM_COLUMN.push(
    {
      Control: this.state.control,
      CreateBy: this.props.user.userId,
      Datatype: this.state.datatype,
      Form_UID: this.props.selectedFormJSON.Form_UID,
      Help: this.state.help,
      ValueStore: this.state.valueStore
    }
  )
  this.props.updateSelectedFormJSON(obj);
  if(!this.props.isNewForm && this.state.valueStore) {
    this.props.patchForm().then((res)=>{
    if(res.Forms[0] && (res.Forms[0].Code === '200' || res.Forms[0].Code===200)) {
      toast(<div>Attribute Added Successfully!</div>, {type: toast.TYPE.SUCCESS,position: toast.POSITION.TOP_LEFT})
    } else {
      toast(<div>Failed to Add Attribute!</div>, {type: toast.TYPE.ERROR,position: toast.POSITION.TOP_LEFT})
    }
  });
  } else if(this.state.valueStore) {
    this.props.postForm().then((res)=>{
      if(res.Forms[0] && (res.Forms[0].Code === '201' || res.Forms[0].Code===201)) {
        toast(<div>Attribute Added Successfully!</div>, {type: toast.TYPE.SUCCESS,position: toast.POSITION.TOP_LEFT})
      } else {
        toast(<div>Failed to Add Attribute!</div>, {type: toast.TYPE.ERROR,position: toast.POSITION.TOP_LEFT})
      }
    })
  }
  this.props.closeModal();
})
}

     addValueAttribute = () => {
return new Promise((resolve, reject) => {
  if(this.state.valueStore) {
    let {valueTables, valueDatatypes, service} = this.state;
    let body = {
      Name: this.state.name,
      TableName: this.props.selectedFormJSON.Entity,
      Datatype: this.state.datatype,
      ChangeType: 'I'
    }
    fetch(service.URL+'/VALUE_ATTRIBUTE', { headers: {
      'Content-Type': 'application/json',
      'Ocp-Apim-Subscription-Key': service.subscription_key,
    },
      method: 'POST',
      credentials: 'include',
      body: JSON.stringify(body),
    })
    .then((res) => {
      res.status === 201 && resolve();
    })
    .catch(() => {
      reject();
    })
  } else {
    //Not a value attr
    resolve()
  }
})

}

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

it("should call onAddClick", async () => {  // use an async test method
baseProps. closeModal.mockClear();
baseProps. updateSelectedFormJSON.mockClear();

const instance = wrapper.instance();
const spy = jest.spyOn(instance, 'addValueAttribute');  // spy on addValueAttribute...
spy.mockImplementation(() => Promise.resolve())  // give any callbacks queued in PromiseJobs a chance to run
wrapper.find('#test-addclick').at(0).simulate('click');  // simulate click

expect(baseProps.updateSelectedFormJSON).toHaveBeenCalled();  // SUCCESS
expect(baseProps.closeModal).toHaveBeenCalled();  // SUCCESS
});

person usertestREACT    schedule 27.02.2019    source источник
comment
Проблема в вызове addValueAttribute., поскольку это шутка с обещанием, не ждите ее. Таким образом, вызов toHaveBeenCalled вызывается до выполнения обещания. Обычно вы решаете такие проблемы, имитируя вызов обещания. Не могли бы вы показать, что происходит внутри addValueAttribute?   -  person Andreas Köberle    schedule 27.02.2019
comment
это будет много кода, но я обновил вопрос   -  person usertestREACT    schedule 27.02.2019
comment
@ AndreasKöberle обновлено !!   -  person usertestREACT    schedule 27.02.2019
comment
Похоже, нет простого способа издеваться над этим. Возможно, вы сможете попробовать это решение: jestjs.io/docs/en/troubleshooting#unresolved-promises   -  person Andreas Köberle    schedule 27.02.2019
comment
Я попробую - спасибо andreas   -  person usertestREACT    schedule 27.02.2019


Ответы (1)


addValueAttribute стоит дорого, поэтому вы захотите высмеять его, чтобы решить немедленно. addValueAttribute - это поле класса, поэтому вам нужно будет имитировать его, используя экземпляр компонента.

Когда вызывается onAddClick, он вызывает this.addValueAttribute, который должен немедленно вернуться. Это приведет к тому, что обратный вызов Promise в then будет добавлен в очередь PromiseJobs. Задания в этой очереди запускаются после завершения текущего сообщения и до начала следующего сообщения.

Это означает, что обратный вызов, который вызывает this.props.updateSelectedFormJSON и this.props.closeModal, помещается в очередь PromiseJobs, когда обработчик кликов возвращается и тест продолжается.

На этом этапе вам нужно приостановить тест, чтобы дать возможность выполнить обратный вызов, помещенный в очередь в PromiseJobs. Самый простой способ сделать это - сделать вашу тестовую функцию async и вызвать await Promise.resolve();, которая, по сути, поставит оставшуюся часть теста в конец очереди PromiseJobs и позволит любым заданиям, уже находящимся в очереди, запускаться первыми.

Собирая все вместе, вот упрощенная версия вашего кода с рабочим тестом:

import * as React from 'react';
import { shallow } from 'enzyme';

class Comp extends React.Component {
  onAddClick = () => {
    this.addValueAttribute().then(() => {
      this.props.updateSelectedFormJSON();
      this.props.closeModal();
    })
  }
  addValueAttribute = () => {
    return new Promise((resolve) => {
      setTimeout(resolve, 100000);  // does something computationally expensive
    });  
  }
  render() {
    return (<button onClick={this.onAddClick}>Create Field</button>);
  }
}

it("should call onAddClick", async () => {  // use an async test method
  const props = {
    updateSelectedFormJSON: jest.fn(),
    closeModal: jest.fn()
  }
  const wrapper = shallow(<Comp {...props} />);
  const instance = wrapper.instance();
  const spy = jest.spyOn(instance, 'addValueAttribute');  // spy on addValueAttribute...
  spy.mockResolvedValue();  // ...and mock it to immediately resolve
  wrapper
    .find('button')
    .at(0)
    .simulate('click');  // simulate click
  await Promise.resolve();  // give any callbacks queued in PromiseJobs a chance to run
  expect(props.updateSelectedFormJSON).toHaveBeenCalled();  // SUCCESS
  expect(props.closeModal).toHaveBeenCalled();  // SUCCESS
});
person Brian Adams    schedule 28.02.2019
comment
Спасибо за ваш ответ. Я вчера решил нечто похожее на это. Я займусь этим прямо сейчас - person usertestREACT; 28.02.2019
comment
spy.mockresolvedValue - это не функция, я получаю это как ответ - person usertestREACT; 28.02.2019
comment
@usertestREACT .mockResolvedValue() был добавлен в Jest версии 22.2.0 поэтому, если вы используете более раннюю версию Jest, используйте вместо нее .mockImplementation(() => Promise.resolve()). - person Brian Adams; 28.02.2019
comment
Брайан, спасибо - теперь я получаю другое сообщение, в котором говорится, что была вызвана ожидаемая фиктивная функция - ошибка: я обновлю свой вопрос / ответ - person usertestREACT; 01.03.2019
comment
@usertestREACT После имитации щелчка отсутствует строка await Promise.resolve();. - person Brian Adams; 01.03.2019
comment
Теперь я столкнулся с другой ошибкой: я видел нечто похожее, но не смог найти файл. Невозможно прочитать свойство then of undefined - person usertestREACT; 04.03.2019
comment
@usertestREACT Пожалуйста, обновите свой код, я не могу помочь с кодом, который не вижу - person Brian Adams; 04.03.2019
comment
Брайан, он возвращается к this.addValueAttribute (). then (() = ›{- он опубликован по моему вопросу. Я уже добавил обещание и решение - person usertestREACT; 04.03.2019
comment
@usertestREACT, если речь идет о вашем последнем коде, значит, вам все еще не хватает строки await Promise.resolve(); после имитации щелчка. Что касается ошибки, вы уверены, что это then, связанный с this.addValueAttribute? Вы уверены, что он не исходит от then, привязанного к this.props.patchForm() или this.props.postForm()? - person Brian Adams; 05.03.2019
comment
верный. Я только что сделал несколько вещей в patchForm и postForm, не могу прочитать свойство then of undefined. Работаю над этим - person user 9191; 18.03.2019
comment
Работает отлично, только этот ответ во всей сети, помог мне решить имитацию async await ... Существует так много контента, который испорчен. - person Dejan; 21.04.2021