酶异步等待模拟函数未被调用

IT技术 javascript reactjs jestjs enzyme
2021-05-14 04:02:40

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

● 应该处理 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

应用程序.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;

应用程序.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
    });

  })
})
1个回答

你可以这样测试:

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,以获得其props和调用其onSubmit功能。

使用的async测试功能,并awaitPromise由归国onSubmit因此它继续之前全部完成。

使用.state查询组件状态。