我正在尝试测试异步等待功能,但是我收到了错误消息。


  ●应该处理getGIF事件›应该处理getGIF事件

expect(jest.fn()).toHaveBeenCalledTimes(1)

Expected mock function to have been called one time, but it was called zero times.



我不确定如何测试异步等待功能,因此我以该博客为例https://medium.com/@rishabhsrao/mocking-and-testing-fetch-with-jest-c4d670e2e167

App.js

import React, {Component} from 'react';
import logo from './logo.svg';
import './App.css';
import Card from './Card';
import PropTypes from "prop-types";
const Styles = {
    marginTop: '100px',
    inputStyle: {
        borderRadius: '0px',
        border: 'none',
        borderBottom: '2px solid #000',
        outline: 'none',
        focus: 'none'
    }
}
class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            query: '',
            title: undefined,
            url: undefined
        }
        this.onChange = this.onChange.bind(this);
    }
    onChange(e) {
        this.setState({query: e.target.value})
    }
    // testing this function
    getGIY = async(e) => {
        e.preventDefault();
        const { query } = this.state;
        await fetch(`http://api.giphy.com/v1/gifs/search?q=${query}&api_key=iBXhsCDYcnktw8n3WSJvIUQCXRqVv8AP&limit=5`)
        .then(response => response.json())
        .then(({ data }) => {
          this.setState({
            title: data[0].title,
            url: data[0].images.downsized.url
          });
        })
        .catch( (err) =>{
            console.log(err)
        });

    }
    render() {
        return (
            <div className="col-md-6 mx-auto" style={Styles}>
                <h1 className="gif-title">Random GIF fetch</h1>
                <form className="form-group" onSubmit={this.getGIY}>
                    <input
                        style={Styles.inputStyle}
                        className="form-control"
                        type="text"
                        value={this.state.query}
                        onChange={this.onChange}
                        placeholder="Search GIF..."/>
                    <button type="submit" className="btn btn-primary mt-4">Get GIF</button>
                </form>
                <Card title={this.state.title} url={this.state.url}/>
            </div>
        );
    }
}
PropTypes.propTypes = {
    onChange: PropTypes.func.isRequired,
    getGIY:PropTypes.func.isRequired,
    title:PropTypes.string.isRequired,
    url:PropTypes.string.isRequired
}
export default App;


App.test.js

import React from 'react';
import ReactDOM from 'react-dom';
import {shallow} from 'enzyme';
import App from './App';



describe('Should handle getGIF event', ()=> {
  it('should handle getGIF event', done => {
    const component = shallow(<App/>)

    const mockSuccessResponse = {};
    const mockJsonPromise = Promise.resolve(mockSuccessResponse);
    const mockQuery = "Owl"

    const mockFetchPromise = Promise.resolve({
      json:() => mockJsonPromise,

    });
    jest.spyOn(global, 'fetch').mockImplementation(()=> mockFetchPromise);

    expect(global.fetch).toHaveBeenCalledTimes(1);
    expect(global.fetch).toHaveBeenCalledWith(`http://api.giphy.com/v1/gifs/search?q=${mockQuery}&api_key=iBXhsCDYcnktw8n3WSJvIUQCXRqVv8AP&limit=5`);

    process.nextTick(() => { // 6
      expect(component.state()).toEqual({
        // ... assert the set state
      });

      global.fetch.mockClear(); // 7
      done(); // 8
    });

  })
})

最佳答案

您可以像这样测试它:

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

describe('Should handle getGIF event', () => {

  let mock, actualFetch;
  beforeEach(() => {
    mock = jest.fn();
    actualFetch = global.fetch;
    global.fetch = mock;
  });
  afterEach(() => {
    global.fetch = actualFetch;
  });

  it('should handle getGIF event', async () => {
    const component = shallow(<App />);
    component.setState({ query: 'Owl' });
    mock.mockResolvedValue({
      json: () => Promise.resolve({
        data: [{
          title: 'the title',
          images: { downsized: { url: 'the url' }}
        }]
      })
    });
    const form = component.find('form');

    await form.props().onSubmit({ preventDefault: () => {} });

    expect(mock).toHaveBeenCalledWith('http://api.giphy.com/v1/gifs/search?q=Owl&api_key=iBXhsCDYcnktw8n3WSJvIUQCXRqVv8AP&limit=5');  // Success!
    expect(component.state('title')).toBe('the title');  // Success!
    expect(component.state('url')).toBe('the url');  // Success!
  });
});




细节

fetch可能没有在Node.js环境中定义,因此只需抓住它,然后用模拟代替它,然后恢复它是一个好方法。

使用.setState设置组件状态。

使用.find获取form,并使用.props访问其道具并调用其onSubmit函数。

使用async测试函数和await Promise返回的onSubmit,以便在继续之前完全完成。

使用.state查询组件状态。

09-27 05:13