Enzyme onclick spy для выполнения теста со стрелкой не работает при тестировании функции со стрелкой

#reactjs #enzyme

#reactjs #enzyme

Вопрос:

как я могу протестировать дочерний компонент onclick.

Пожалуйста, посмотрите фрагмент ниже.

 // App.js

import React, {Component, Fragment} from 'react'
import Child from './child'

class App extends Component{

  state = {
    data: null,
    enable: false
  }

  componentDidMount(){
    this.getData()
  }

  getData = async () => {
    const response = await fetch('http://www.example.com');
    const data = await response.json();
    this.setState({
      data
    })
  }

  _handleChildClick = () => {
    this.setState({
      enable: true
    })
  }

  render(){
    const {data, enable} = this.state
    if(!data){
      return (
       <div>
         Loading
       </div>
      )
    }else{
      <Fragment>
        <Child
         handleChildClick={this._handleChildClick}
        />
      </Fragment>
    }
  }
}


export default App


import React from 'react';

const child = () => {
  return(
    <div>
      <button
        className="toggle"
        onClick={props.handleChildClick}
      >
      Toggle
      </button>
    </div>
  )
}

export default child

// App.test.js

import React from 'react';
import {enzyme} from 'enzyme';
import App from './App';

describe("App test cases", () => {
  it('should trigger _handleChildClick', async () => {
    window.fetch = jest.fn().mockImplementation(() => ({
      status: 200,
      json: () => new Promise((resolve, reject) => {
        resolve(
            {
              name: "some data"
            }
        )
      })
    })) 
    const mountWrapper = await mount(<App />)
    setTimeout(() => {
       mountWrapper.update()
             const SpyhandleChildClick = jest.spyOn(mountWrapper.instance(),'_handleChildClick')
      mountWrapper.find('.toggle').simulate('click')
      expect(SpyhandleChildClick).toHaveBeenCalled() // not called 
    },0)
  })
})
  

Комментарии:

1. Привет @DILEEPTHOMAS Ты нашел ответ?

Ответ №1:

Некоторые важные моменты, которые следует учитывать.

Асинхронный код в ваших тестах

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

 setTimeout(() => {
   mountWrapper.update()
         const SpyhandleChildClick = jest.spyOn(mountWrapper.instance(),'_handleChildClick')
  mountWrapper.find('.toggle').simulate('click')
  expect(SpyhandleChildClick).toHaveBeenCalled() // not called 
},0)
  

Выше в вашем коде у вас есть сегмент тайм-аута. Любое тестовое условие внутри этого блока кода не будет оценено, поскольку к моменту их оценки ваш «тестовый сеанс» уже будет завершен из-за характера aync.

Тестирование функций со стрелкой в React с помощью enzyme — forceUpdate()

Похоже, что существует проблема с библиотекой enzyme, где вам приходится принудительно обновлять компонент react после того, как вы следите за тем, чтобы он привязался к методу. Пожалуйста, следите за выпуском github для получения дополнительной информации:https://github.com/airbnb/enzyme/issues/365

Я также немного почистил ваш тестовый код, чтобы сделать его более понятным!

 // App.test.js

import React from 'react';
import {enzyme} from 'enzyme';
import App from './App';


describe("App test cases", () => {
  it("should trigger _handleChildClick", async () => {
    window.fetch = jest.fn().mockImplementation(() => ({
      status: 200,
      json: () =>
        new Promise((resolve, reject) => {
          resolve({
            name: "some data"
          });
        })
    }));

    const mountWrapper = mount(<App />);
    mountWrapper.update();
    console.log("mountWrapper", mountWrapper.debug()); // showing the loader one

    //[FIX]This code will block and wait for your asynchronous tasks to be completed
    await new Promise(res => setTimeout(() => res(), 0));

    mountWrapper.update();
    console.log("mountWrapper", mountWrapper.debug()); // nothing showing
    expect(mountWrapper.find(".toggle").length).toEqual(1);

    //[FIX]Get a reference from the wrapper and force update after the spyOn call
    const instance = mountWrapper.instance();
    const spy = jest.spyOn(instance, "_handleChildClick");
    instance.forceUpdate();

    mountWrapper.find(".toggle").simulate("click");

    expect(spy).toHaveBeenCalled();
  });
});
  

Ссылка на демонстрационную версию: Нажмите на вкладку «Тесты» в браузере, чтобы увидеть результаты теста
https://codesandbox.io/s/mz21kpm37j