Издевательская функция класса ES6 с Jest

У меня вопрос о том, как я могу высмеять экземпляр класса ES6 с помощью Jest, который используется методом, который я действительно хочу проверить. В моем реальном случае мы пытаемся протестировать создателя action-асинхронного 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() в каждом тесте, чтобы вызвать success и обратные вызовы error без вызова метода post.

Я только getData() издеваться над функцией getData() для всего тестового файла с этим фрагментом вверху:

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

но я не могу переключиться между реализацией в другом тестовом случае.

Я полагаю, что что-то, использующее .mockImplementation() может делать вещи, но я не могу сделать эту работу в моем случае (я видел примеры, использующие ее для экспорта модулей, но не для классов).

У кого-нибудь есть идея?

Изменить:

Я забыл часть в примере кода: создание экземпляра класса связи, которое, я думаю, является "проблемой" для издевательства над ним:

const com = new communication();

Если com инициируется на глобальном уровне в файле communicationatorAssist.js: он не работает с message.getData не является функцией ошибки.

Но если я устанавливаю instanciation внутри функции retrieveData(), фрагмент Andreas Köberle отлично работает:

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

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

(jest.mock() параметр фабрики должен возвращать функцию не напрямую jest.fn)

Я не знаю, почему он не работает с использованием экземпляра глобальной области массива.

Ответ 1

Вам нужно смоделировать модуль с помощью jest.fn(), затем вы можете импортировать его и изменить его поведение, используя mockImplementation:

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

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

Ответ 2

Если вы хотите вернуть результат вызову функции на 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