javascript 用 Jest 模拟 ES6 类函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46500749/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 06:42:44  来源:igfitidea点击:

Mocking an ES6 class function with Jest

javascriptunit-testingreact-reduxjestjs

提问by Imk

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.

我有一个关于如何使用 Jest 模拟 ES6 类实例的问题,Jest 由我实际想要测试的方法使用。我的真实案例是尝试测试一个 Redux 异步操作创建器,该创建器发出请求并根据请求结果分派一些操作。

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 successand errorcallbacks without any call to post method.

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

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

我只成功模拟了getData()整个测试文件的功能,并在其顶部使用此代码段:

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 ).

我认为使用.mockImplementation()的东西可以做这些事情,但在我的情况下我无法做到这一点(我看到了将它用于模块导出功能但不是用于类的示例)。

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 comis instanciated at a global level in the communicatorAssist.js file : it fail with communication.getData is not a functionerror.

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

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

但是,如果我在retrieveData()函数内设置实例化,Andreas K?berle 片段就可以正常工作:

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)

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

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

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

回答by Andreas K?berle

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

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

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

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