如何在Jest中手动模拟自己的一个文件?

The*_*Fox 12 javascript unit-testing reactjs jestjs

我正在尝试在Jest中模拟一个对象(我创建的),因此我可以在react组件中提供默认行为(因此不使用真正的实现)

这是我的反应组件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;
Run Code Online (Sandbox Code Playgroud)

所以我有一个自定义的I18n依赖项进行翻译(I18n是我写的,它是node-polyglot的包装器).

所以我想做一个基本测试,看看H1中是否有正确的单词,但我不想在我的I18n对象上设置jest.dontMock(),因为我不希望它使用真实对象在ChatApp测试中.

因此,按照开玩笑网站上的基本说明,我创建了一个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;
Run Code Online (Sandbox Code Playgroud)

现在在我的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');
  });
});
Run Code Online (Sandbox Code Playgroud)

如果我在测试中调试i18n对象,那么我得到正确的模拟对象,__ setReturnString也会被触发(好像我在该消息中的console.log中看到了日志).

但是,如果我在实际的React组件中调试i18n对象,那么它会获得一个Jest模拟,但它不会得到我的Jest模拟,所以t方法是一个没有做任何事情的空方法,这意味着测试失败.

我有什么想法我做错了吗?

非常感谢

小智 7

我也无法使__mocks__文件夹正常工作.我绕过它的jest.setMock();方法是使用该方法.

在你的情况下,你会的 jest.setMock('../../../scripts/i18n/', require('../__mocks__/i18n');

显然,我不确定你的模拟的位置和你正在使用的真实库的位置,但是第一个参数应该使用存储真实模块的路径,第二个参数应该使用模拟存储的路径.

这应该强制您的模块和您需要的所有模块(包括React)使用您手动模拟的i18n模块.


kra*_*raf 1

Jest 会自动嘲笑。应该i18n = require('../support/i18n')就够了。这就是为什么你通常必须jest.dontMock首先打电话。

您可以在这里找到更多信息:https://facebook.github.io/jest/docs/automatic-mocking.html

  • 嗨,我尝试要求该事物并模拟该值,但在实际实现中(在 ChatApp 内),当调用 t 时,它仍然返回未定义,因此模拟不起作用。测试中的 i18n 对象已正确模拟,但这不是 ChatApp 代码中使用的 i18n 对象。 (2认同)
  • 请注意,截至 2016 年,jest 默认情况下不再进行自动模拟:https://web.archive.org/web/20171011061608/https://facebook.github.io/jest/blog/2016/09/01/jest -15.html - 您可以按照 https://web.archive.org/web/20171011043302/https://facebook.github.io/jest/docs/en/configuration.html#automock-boolean 重新启用它 (2认同)