it-roy-ru.com

Как вы вручную издеваетесь над одним из ваших собственных файлов в Jest?

Я пытаюсь смоделировать объект (который я создал) в Jest, чтобы я мог обеспечить поведение по умолчанию в компоненте реагирования (чтобы реальная реализация не использовалась)

Это мой компонент реагирования ChatApp (это очень прямо)

'use strict';
var React, ChatApp, ChatPanel, i18n;

React = require('react');
ChatPanel = require('./chat_panel');
i18n = require('../support/i18n');

ChatApp = React.createClass({
  render() {
    return (
      <div className="chat-app">
        <h1>{i18n.t("app.title")}</h1>
        <ChatPanel />
      </div>
    );
  }
});

module.exports = ChatApp;

Поэтому у меня есть пользовательская зависимость I18n, которая выполняет переводы (I18n - это то, что я написал, это оболочка для узла-полиглота).

Поэтому я хочу провести базовый тест, чтобы увидеть, есть ли в H1 правильное слово Word, но я не хочу устанавливать jest.dontMock () для моего объекта I18n, потому что я не хочу, чтобы он использовал реальный объект в тесте ChatApp.

Следуя основным инструкциям на веб-сайте jest, я создал папку mocks и создал фиктивный файл для i18n, который генерирует макет из исходного объекта, а затем переопределяет метод t и добавляет метод, позволяющий мне установить возвращаемую строку для т.

Это фиктивный объект

'use strict';
var i18nMock, _returnString;

i18nMock = jest.genMockFromModule('../scripts/support/i18n');

_returnString = "";

function __setReturnString(string) {
  _returnString = string;
}

function t(key, options = null) {
  return _returnString;
}

i18nMock.t.mockImplementation(t);
i18nMock.__setReturnString = __setReturnString;

module.exports = i18nMock;

Теперь в моем тесте ChatApp мне требуется макет перед каждым, например, так:

'use strict';
var React, ChatApp, TestUtils, path;

path = '../../../scripts/components/';
jest.dontMock( path + 'chat_app');

React = require('react/addons');
ChatApp = require( path + 'chat_app');
TestUtils = React.addons.TestUtils;

describe('ChatApp', () => {
  beforeEach(() => {
    require('i18n').__setReturnString('Chat App');
  });

  var ChatAppElement = TestUtils.renderIntoDocument(<ChatApp />);

  it('renders a title on the page', () => {
    var title = TestUtils.findRenderedDOMComponentWithTag(ChatAppElement, 'h1');
    expect(title.tagName).toEqual('H1');
    expect(title.props.children).toEqual('Chat App');
  });
});

Если я console.log объекта i18n в тесте, то я получаю правильный макет объекта, __setReturnString также срабатывает (как будто я console.log в этом сообщении я вижу журнал).

Однако, если я console.log объекта i18n внутри фактического компонента React, он получает Jest-макет, но не получает Jest-макет, поэтому метод t - это пустой метод, который не выполняет все, что означает, что тест не пройден.

Есть идеи, что я делаю не так?

Большое спасибо

12
TheStoneFox

У меня возникли проблемы с работой папки __mocks__. Я обошел это путем использования метода jest.setMock();.

В вашем случае вы бы jest.setMock('../../../scripts/i18n/', require('../__mocks__/i18n');

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

Это должно заставить ваш модуль и все ваши модули (включая React) использовать ваш вручную смоделированный модуль i18n.

6
MattyKuzyk

Шут делает автоматический насмешливый. Просто i18n = require('../support/i18n') должно быть достаточно. Вот почему вы обычно должны вызывать jest.dontMock в первую очередь.

Вы можете найти дополнительную информацию здесь: https://facebook.github.io/jest/docs/automatic-mocking.html

1
kraf

Что Маттикузык упоминает в его ответ у меня вообще не сработало :(

Однако то, что я обнаружил, казалось, было проблемой для меня, была настройка шутки: я использовал moduleNameMapper в начале, и по какой-то причине они никогда не издевались ...

Поэтому для меня первым шагом было вместо этого переместить папку с именем моего модуля в moduleDirectories, чтобы все заработало.

После этого я мог бы просто добавить файл __mocks__ рядом с фактической реализацией (в моем случае utils/translation.js и utils/__mocks__/translation.js) . Поскольку мой translations.js по умолчанию экспортирует функцию перевода, я также по умолчанию экспортировал мой макет. Весь __mocks__/translations.js супер просто и выглядит так:

export default jest.fn((key, unwrap = false) => (
    unwrap && `${key}-unwrapped` || `${key}-wrapped`
))

Хотя я не проверял это, добавить __setReturnString должно быть достаточно просто, для меня было достаточно фактически вернуть мой ключ перевода. Надеюсь это поможет!

0
Iris Schaffer