Jest manual mocking works only for the first function call

Razvan-Catalin Olaru

I've mocked a custom XHR wrapper that I've written (utils/xhr.js) using Jest manual mocking feature and the issue that I'm having is that only the first XHR call is tracked:

utils/xhr.js

let xhr = {
    get: function(params) { /* XHR get implementation */ }
    post: function(params) { /* XHR post implementation */ }
};

export default xhr;

utils/__mocks__/xhr.js - the mock implementation

let xhr = jest.genMockFromModule('./../xhr');

module.exports = xhr;

Dashboard.api.js - the XHR calls for the dashboard component

// ...

getTrendingEntities: (days, maxItems) => {

    return xhr.get({url: '/api/aggregator/riskEntities/' +  days + '/' + maxItems})
        .then((response) => {
            companyIds = parseCompanies(response.body);

            return xhr.post({
                url: '/api/entities/specific-companies',
                data: companyIds
            });

        }).then((response) => {
            let companies = parseCompaniesData(response.body);

            return Promise.resolve(companies);
        });
}

// ...

TrendingEntitiesPod.jsx - the React component that uses Dashboard.api.js

class TrendingEntitiesPod extends React.Component {

    // ...

    componentWillMount() {
        this.loadData(this.props.days)
    }

    componentWillReceiveProps(nextProps) {
        if (this.props.days != nextProps.days) {
            this.loadData(nextProps.days);
        }
    }

    loadData(days) {
        this.setState({loading: true});

        api.getTrendingEntities(days, DASHBOARD_PODS_ENTRIES_NUMBER)
            .then((companies) => {
                this.setState({
                    companies: companies,
                    loading:   false
                });
            });
    }

    render() { // ... }

}

StartPage.TrendingEntitiesPod.spec.js - the test file

import React from 'react';
import { mount } from 'enzyme';

import xhr from './../../../utils/xhr';
jest.mock('./../../../utils/xhr');

import TrendingEntitiesPod from './../Dashboard/components/TrendingEntitiesPod/TrendingEntitiesPod.jsx';

describe('StartPage.TrendingEntitiesPod:', () => {

    let wrapper = null;

    beforeAll(() => {
        xhr.get.mockReturnValueOnce(Promise.resolve({body: trendingEntities}));
        xhr.post.mockReturnValueOnce(Promise.resolve({body: trendingEntitiesData}));
        xhr.get.mockReturnValue(Promise.resolve({body: trendingEntityPestleData}));

        wrapper = mount(<TrendingEntitiesPod days={30} />);

    });

    test('...stubbing works', () => {
        expect(xhr.get.mock.calls.length).toBe(1);
        expect(xhr.post.mock.calls.length).toBe(1); // returns false - why??
    });

});
Razvan-Catalin Olaru

Another way to deal with this issue, as it seems that Jest doesn't play well when doing setTimeout() all the time, is to not test the component's state after all initial requests have done. You can test the individual methods that do the XHR requests (and data parsing logic/component state change). E.g.:

AirlineCompanies.jsx

class AirlineCompanies extends React.Component {

    // ...

    loadData(numberOfCompanies) {
        this.setState({loading: true});

        return api.getAirlineCompanies(numberOfCompanies)
            .then((companies) => {
                this.setState({
                companies: companies,
                loading:   false
            });
        })
        .catch((error) => {
            utils.logError(error, 'AirlineCompanies.loadData():');
            this.setState({loading: false});
        });
    }

    // ...

}

AirlineCompanies.spec.js

let component = mount(<AirlineCompanies />).instance();
let airlineCompaniesData = [ /*... mock companies data ...*/ ];

it('...should have the state changed and eight AirlineCompany components after data is loaded', (done) => {
    xhr.get.mockReturnValueOnce(Promise.resolve({body: airlineCompaniesData}));

    component.loadData(30).then(() => {
        expect(wrapper.state('companies')).toEqual(airlineCompaniesData);
        expect(wrapper.find(AirlineCompany).length).toBe(8);
        done();
    });

});

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Mocking a function call in Jest

Mocking a function call inside a function in Jest

Jest - Mocking a function call within the handleSubmit of a form

Why to group list of object by an Id works only at first call in that function?

Mocking an object in Jest that has a function that makes an Axios call

Jest - Mocking a factory function

Mocking private method with PowerMockito only works starting with second method call

Function works on first call, but on second call it does not

Jest mocking function inside function

Node Jest mocking a function in a function

$q.all works for the first call only

Specify function parameter in jest mocking

Why does changing parameters inside map async loop only works on first async function call?

mocking a function call in midje

Recursive function that works on first call but not on second

onClick function only works for the first time in react?

Button function only works on first click

javascript function only works with first element

Why JQuery function works for only the first textbox

Recursive function only works for first level of array

vim function only works properly the first time

Toggles class function only works on first element

jquery function works correctly only on first click

Javascript function ONLY works on the first row of the table

Function works correctly only the first time it is called

strcmp() function only works on first iteration C

In nested functions only the first function works

Only first row works for amount function

javascript - function only works on second call

TOP Ranking

HotTag

Archive