Jest — Mock a function called inside a React Compo

2019-03-16 03:25发布

问题:

Jest provides a way to mock functions as described in their docs

apiGetMethod = jest.fn().mockImplementation(
    new Promise((resolve, reject) => {
        const userID = parseInt(url.substr('/users/'.length), 10);
        process.nextTick(
            () => users[userID] ? resolve(users[userID]) : reject({
                error: 'User with ' + userID + ' not found.',
            });
        );
    });
);

However these mocks only seem to work when the function is called directly in a test.

describe('example test', () => {
    it('uses the mocked function', () => {
        apiGetMethod().then(...);
    });
});

If I have a React Component defined as such how can I mock it?

import { apiGetMethod } from './api';

class Foo extends React.Component {
    state = {
        data: []
    }

    makeRequest = () => {
       apiGetMethod().then(result => {
           this.setState({data: result});
       });
    };

    componentDidMount() {
        this.makeRequest();
    }

    render() {
        return (
           <ul>
             { this.state.data.map((data) => <li>{data}</li>) }
           </ul>
        )   
    }
}

I have no idea how to make it so Foo component calls my mocked apiGetMethod() implementation so that I can test that it renders properly with data.

(this is a simplified, contrived example for the sake of understanding how to mock functions called inside react components)

edit: api.js file for clarity

// api.js
import 'whatwg-fetch';

export function apiGetMethod() {
   return fetch(url, {...});
}

回答1:

You have to mock the ./api module like this and import it so you can set the implemenation of the mock

import { apiGetMethod } from './api'

jest.mock('./api', () => ({ apiGetMethod: jest.fn() }))

in your test can set how the mock should work using mockImplementation:

apiGetMethod.mockImplementation(() => Promise.resolve('test1234'))


回答2:

In case the jest.mock method from @Andreas's answer did not work for you. you could try the following in your test file.

const api = require('./api');
api.apiGetMethod = jest.fn(/* Add custom implementation here.*/);

This should execute your mocked version of the apiGetMethod inside you Foo component.



回答3:

Another solution to mock this would be:

window['getData'] = jest.fn();