Jest: Как издеваться над компонентом экспорта по умолчанию, когда тот же модуль также назвал экспорт?

У меня есть модуль ES6, который по умолчанию экспортирует класс React Component, но также экспортирует простую JS-функцию как именованный экспорт. При тестировании других пакетов, которые используют этот модуль, я хочу высмеять как экспортированный по умолчанию компонент, так и названную экспортированную функцию, чтобы мои чистые тесты были чистыми.

Модуль выглядит примерно так:

import React, { Component } from 'react';

export default class MyComponent extends Component {
  render() {
    return <div>Hello</div>
  }
}

export function myUtilityFunction() { return 'foo' };

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

import React from 'react';
import MyComponent, { myUtilityFunction } from './module';

jest.mock('./module');
MyComponent.mockImplementation(() => 'MockComponent');
myUtilityFunction.mockImplementation(() => 'foo');

Однако, когда я пытаюсь использовать этот синтаксис, MyComponent не выглядит издеваемым при использовании в других компонентах. Когда я пытаюсь издеваться над MyComponent как это и самостоятельно выносить его, он отображает значение null.

Такое поведение очень странно, потому что, если я использую тот же синтаксис, но оба импорта являются функциями JavaScript, насмешливые работы, как и ожидалось. См. Проблему StackOverflow, которую я открыл здесь, которая подтверждает, что синтаксис работает, когда импорт является обеими функциями.

Вот репозиторий GitHub, демонстрирующий проблему, а также несколько решений, которые я пробовал: https://github.com/zpalexander/jest-enzyme-problem

Вы можете построить репо и запустить тесты с помощью теста пряжи && пряжи

Спасибо!

Ответ 1

Другое решение не сработало для меня. Вот как я это сделал:

  jest.mock('./module', () => ({
    __esModule: true,
    myUtilityFunction: 'myUtilityFunction',
    default: 'MyComponent'
  }));

Другой способ сделать это:

jest.unmock('../src/dependency');

const myModule = require('../src/dependency');
myModule.utilityFunction = 'your mock'

Ответ 2

Я думаю, проблема заключается в том, что методу getElement класса ShallowWrapper необходимо передать класс, содержащий метод рендеринга. Для этого ваш MyComponent.mockImplementation должен более полно издеваться над конструктором класса.

Подробнее о том, как издеваться над конструктором класса, см. Документацию Jest, начиная с "mockImplementation", также можно использовать для моделирования конструкторов классов: https://facebook.github.io/jest/docs/en/mock-function-api. HTML # mockfnmockimplementationfn

Используя документацию Jest в качестве модели, мы можем высмеять конструктор класса MyComponent и сделать его мелким визуализируемым ферментом следующим образом:

MyComponent.mockImplementation(() => {
  return {
    render: () => <div>MockComponent</div>
  };
});

Теперь, когда getElement ищет метод визуализации, он найдет его.

Вот суть, которая реализует это изменение в файле App.mockImplementation.test.js из вашего репо: https://gist.github.com/timothyjellison/a9c9c2fdfb0b30aab5698dd92e901b24