最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Mocking an ES6 class function with Jest - Stack Overflow

programmeradmin3浏览0评论

I have a question about how can I mock an ES6 class instance using Jest which is used by the method I actually want to test. My real case is trying to test a Redux async action creator that make a request and dispatch some action depending on the request result.

This is a simplified example of the use case :

// communication.js
// An exported ES6 class module with proxy to the request library.
import post from './post';
export default class communication {

    getData(data, success, error) {
        const res = post(data);
        if(res) {
            success();
        } else {
            error();
        }
    }
}

// communicatorAssist.js
// A redux async function using communication.js
import communication from './communication';
// ...

export function retrieveData() {
    return dispatch => {
        const data = { name: 'michel'};
        communication.getData(data,
            (res) => dispatch(successAction(res)),
            (res) => dispatch(errorAction(res));
    }
}

// communicatorAssist.test.js testing the communicatorAssist
import { retrieveData } from 'communicatorAssist';

// communication.getData should call success callback
// for this test.
it('Should call the success callback', () => {
    retrieveData();
    // Assert that mocked redux store contains actions
});

// communication.getData should call error callback
// for this test.
it('Should call the error callback', () => {
    retrieveData();
    // Assert that mocked redux store contains actions
});

What I want is mocking the communication class in the test and change the behaviour of the getData() function in each test to call success and error callbacks without any call to post method.

I only success to mock the getData() function for the whole test file with this snippet at the top of it :

import communication from '../communication'
jest.mock('../communication', () => (() => ({
    getData: (success, error) => success()
})));

but I can't switch between implementation in different test case.

I figure that something using .mockImplementation() could do the stuff but I can't make this work in my case (I saw examples using it for module exporting functions but not for classes ).

Does anyone have an idea ?

Edit :

I forgot a part in the code exemple : the communication class instance creation which I think is the "problem" for mocking it :

const com = new communication();

If com is instanciated at a global level in the communicatorAssist.js file : it fail with communication.getData is not a function error.

But if I set the instanciation inside the retrieveData() function, Andreas Köberle snippet work's fine :

import communication from '../communication'
jest.mock('../communication', () => jest.fn());

communication.mockImplementation(
  () => ({
    getData: (success, error) => success()
  })
)

(jest.mock() factory parameter need to return a function not directly jest.fn)

I don't know why it's not working using a file global scope instance.

I have a question about how can I mock an ES6 class instance using Jest which is used by the method I actually want to test. My real case is trying to test a Redux async action creator that make a request and dispatch some action depending on the request result.

This is a simplified example of the use case :

// communication.js
// An exported ES6 class module with proxy to the request library.
import post from './post';
export default class communication {

    getData(data, success, error) {
        const res = post(data);
        if(res) {
            success();
        } else {
            error();
        }
    }
}

// communicatorAssist.js
// A redux async function using communication.js
import communication from './communication';
// ...

export function retrieveData() {
    return dispatch => {
        const data = { name: 'michel'};
        communication.getData(data,
            (res) => dispatch(successAction(res)),
            (res) => dispatch(errorAction(res));
    }
}

// communicatorAssist.test.js testing the communicatorAssist
import { retrieveData } from 'communicatorAssist';

// communication.getData should call success callback
// for this test.
it('Should call the success callback', () => {
    retrieveData();
    // Assert that mocked redux store contains actions
});

// communication.getData should call error callback
// for this test.
it('Should call the error callback', () => {
    retrieveData();
    // Assert that mocked redux store contains actions
});

What I want is mocking the communication class in the test and change the behaviour of the getData() function in each test to call success and error callbacks without any call to post method.

I only success to mock the getData() function for the whole test file with this snippet at the top of it :

import communication from '../communication'
jest.mock('../communication', () => (() => ({
    getData: (success, error) => success()
})));

but I can't switch between implementation in different test case.

I figure that something using .mockImplementation() could do the stuff but I can't make this work in my case (I saw examples using it for module exporting functions but not for classes ).

Does anyone have an idea ?

Edit :

I forgot a part in the code exemple : the communication class instance creation which I think is the "problem" for mocking it :

const com = new communication();

If com is instanciated at a global level in the communicatorAssist.js file : it fail with communication.getData is not a function error.

But if I set the instanciation inside the retrieveData() function, Andreas Köberle snippet work's fine :

import communication from '../communication'
jest.mock('../communication', () => jest.fn());

communication.mockImplementation(
  () => ({
    getData: (success, error) => success()
  })
)

(jest.mock() factory parameter need to return a function not directly jest.fn)

I don't know why it's not working using a file global scope instance.

Share Improve this question edited Oct 1, 2017 at 6:17 Imk asked Sep 30, 2017 at 7:54 ImkImk 2011 gold badge2 silver badges9 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 17

You need to mock the module with jest.fn() then you can import it and change the behaviour of it using mockImplementation:

import communication from '../communication'
jest.mock('../communication', jest.fn());

communication.mockImplementation(
  () => ({
    getData: (success, error) => success()
  })
)
发布评论

评论列表(0)

  1. 暂无评论