我试图在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是我写的,它是节点多语言的包装器)。
所以我想做一个基本测试,看看H1中是否有正确的单词,但我不想在我的I18n对象上设置jest.dontMock(),因为我不是希望它在ChatApp测试中使用真实对象。
所以按照开玩笑网站上的基本说明,我创建了一个 mocks 文件夹并为i18n创建了一个模拟文件,它从原始对象生成一个模拟,然后覆盖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');
});
});
如果我在测试中控制了i18n对象,那么我得到了正确的模拟对象,__ setReturnString也会被触发(好像我在该消息中的console.log中看到了日志)。
但是,如果我在实际的React组件中调试i18n对象,那么它会获得一个Jest模拟,但它没有得到我的Jest模拟,所以t方法是一个空方法,不是做任何事情,意味着测试失败。
任何想法我做错了什么?
非常感谢
答案 0 :(得分:7)
我无法让__mocks__
文件夹正常工作。我解决它的方法是使用jest.setMock();
方法。
在您的情况下,您会jest.setMock('../../../scripts/i18n/', require('../__mocks__/i18n');
显然,我不确定你的模拟的位置和你正在使用的真实库的位置,但是第一个参数应该使用存储真实模块的路径,第二个参数应该使用你的实际模块的路径模拟存储。
这会强制您的模块和您需要的所有模块(包括React)使用您手动模拟的i18n模块。
答案 1 :(得分:1)
Jest进行自动模拟。只需i18n = require('../support/i18n')
即可。这就是为什么你通常必须首先打电话给jest.dontMock
。
您可以在此处找到更多信息:https://facebook.github.io/jest/docs/automatic-mocking.html
答案 2 :(得分:0)
mattykuzyk中提到的his answer对我来说根本不起作用:(
然而,我发现的似乎是我的问题是开玩笑的设置:我在开始时使用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`
))
&#13;
虽然我还没有对其进行测试,但添加__setReturnString
应该很容易,对我来说,实际返回我的翻译密钥就足够了。希望这有帮助!