使用Jest模拟ES6类函数

时间:2017-09-30 07:54:09

标签: javascript unit-testing react-redux jestjs

我有一个问题,如何使用Jest模拟ES6类实例,我实际想要测试的方法使用Jest。 我的实际情况是尝试测试一个Redux异步操作创建者,它会发出请求并根据请求结果发送一些操作。

这是用例的简化示例:

// 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
});

我想要的是模拟测试中的通信类,并在每个测试中更改getData()函数的行为,以调用successerror回调,而无需调用post方法。

我只是成功地使用此片段顶部的整个测试文件模拟getData()函数:

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

但我无法在不同的测试用例中切换实现。

我认为使用.mockImplementation()的东西可以完成这些工作,但我不能在我的情况下使用它(我看到的例子用于模块导出函数但不用于类)。

有没有人有想法?

修改

我忘记了代码示例中的一部分:我认为通信类实例创建是模拟它的“问题”:

const com = new communication();

如果com在communicatorAssist.js文件中的全局级别实例化:它会因 communication而失败.getData不是函数错误。

但是如果我在retrieveData()函数中设置了instanciation,那么AndreasKöberle片段的工作很好:

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

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

jest.mock()工厂参数需要不直接返回函数jest.fn

我不知道为什么它不能使用文件全局范围实例。

2 个答案:

答案 0 :(得分:9)

您需要使用jest.fn()模拟该模块,然后您可以导入它并使用mockImplementation更改其行为:

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

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

答案 1 :(得分:0)

如果要将结果返回到UsedClass上的函数调用。

import UsedClass from './usedClassPath'

jest.mock('./usedClassPath');

test("some test", () => {
  const usedClassMockInstance = new UsedClass();

//mock implementation here
  usedClassMockInstance.usedClassMethod = jest.fn().mockImplementation(async () => {
    return returnValueYourMethodMightReturn;
  });

//your test here

})

现在UsedClass已被模拟,并且userClassMethod返回了您希望它返回的内容,即returnValueYourMethodMightReturn