【问题标题】:How do you manually mock one of your own files in Jest?您如何在 Jest 中手动模拟您自己的文件之一?
【发布时间】:2015-04-15 09:30:35
【问题描述】:

我正在尝试在 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;

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

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

所以按照 jest 网站上的基本说明,我创建了一个 mocks 文件夹,并为 i18n 创建了一个 mock 文件,它从原始对象生成一个 mock,然后覆盖 t 方法并添加一个方法允许我为 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 实际 React 组件中的 i18n 对象,那么它会得到一个 Jest 模拟,但它没有得到我的 Jest 模拟,所以 t 方法是一个不做任何事情的空方法,这意味着测试失败。

任何想法我做错了什么?

非常感谢

【问题讨论】:

    标签: javascript unit-testing reactjs jestjs


    【解决方案1】:

    我无法让__mocks__ 文件夹正常工作。我解决它的方法是使用jest.setMock(); 方法。

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

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

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

    【讨论】:

      【解决方案2】:

      Jest 会自动模拟。只需i18n = require('../support/i18n') 就足够了。这就是为什么您通常必须首先致电jest.dontMock

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

      【讨论】:

      • 您好,感谢您的意见。但是,我不希望 Jest 提供自动模拟,因为 Jest 自动模拟函数不返回任何内容。这会使我的测试失败,因为它期望一个字符串被翻译和返回。对开玩笑文档的手动模拟应该是我所需要的,因为我想要一个模拟版本的对象,它可以完全返回我告诉它的内容。
      • 尝试坚持使用自动模拟并在测试中配置模拟如何?类似 `var i18n = require('i18n'); i18n.t.mockReturnValue('我的返回字符串')
      • 嗨,我尝试要求这个东西并模拟这个值,但是在实际实现中(在 ChatApp 内部),当调用 t 时它仍然返回未定义,所以模拟不起作用。测试中的 i18n 对象已正确模拟,但这不是 ChatApp 代码中使用的 i18n 对象。
      • 请注意,自 2016 年起,jest 默认不再自动模拟:web.archive.org/web/20171011061608/https://facebook.github.io/… - 您可以根据 web.archive.org/web/20171011043302/https://facebook.github.io/… 重新启用它
      【解决方案3】:

      mattykuzykhis answer 中提到的内容对我来说根本不起作用:(

      然而,我发现问题似乎是 jest 的设置:我一开始使用了moduleNameMapper,但由于某种原因,这些从未被嘲笑过......

      所以对我来说,第一步是将我的模块名称映射文件夹移动到 moduleDirectories 以使任何工作正常。

      之后,我可以简单地在实际实现旁边添加一个__mocks__ 文件(在我的例子中是utils/translation.jsutils/__mocks__/translation.js)。 由于我的translations.js 默认导出了一个翻译函数,我也默认导出了我的模拟。整个__mocks__/translations.js超级简单,长这样:

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

      虽然我还没有测试过,但添加__setReturnString 应该很容易,对我来说,实际上返回我的翻译密钥就足够了。希望这会有所帮助!

      【讨论】:

        猜你喜欢
        • 2018-04-06
        • 1970-01-01
        • 2021-03-14
        • 2018-09-04
        • 2019-02-02
        • 1970-01-01
        • 2017-05-23
        • 2018-02-13
        • 1970-01-01
        相关资源
        最近更新 更多