简体   繁体   English

用 Jest 模拟 ES6 类函数

[英]Mocking an ES6 class function with Jest

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.我有一个关于如何使用 Jest 模拟 ES6 类实例的问题,Jest 由我实际想要测试的方法使用。 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.我的真实案例是尝试测试 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 success and error callbacks 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 com is instanciated at a global level in the communicatorAssist.js file : it fail with communication.getData is not a function error.如果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.我不知道为什么它不能使用文件全局作用域实例。

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()
  })
)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM