我使用create-app-component创建了一个项目,它使用构建脚本(babel,webpack,jest)配置了一个新的应用程序。
我写了一个React组件,我正在测试。该组件需要另一个JavaScript文件,公开一个函数。
我的search.js文件
export {
search,
}
function search(){
// does things
return Promise.resolve('foo')
}
字符串
我的react组件:
import React from 'react'
import { search } from './search.js'
import SearchResults from './SearchResults'
export default SearchContainer {
constructor(){
this.state = {
query: "hello world"
}
}
componentDidMount(){
search(this.state.query)
.then(result => { this.setState({ result, })})
}
render() {
return <SearchResults
result={this.state.result}
/>
}
}
型
在我的单元测试中,我想检查方法search
是否被正确的参数调用。
我的测试看起来像这样:
import React from 'react';
import { shallow } from 'enzyme';
import should from 'should/as-function';
import SearchResults from './SearchResults';
let mockPromise;
jest.mock('./search.js', () => {
return { search: jest.fn(() => mockPromise)};
});
import SearchContainer from './SearchContainer';
describe('<SearchContainer />', () => {
it('should call the search module', () => {
const result = { foo: 'bar' }
mockPromise = Promise.resolve(result);
const wrapper = shallow(<SearchContainer />);
wrapper.instance().componentDidMount();
mockPromise.then(() => {
const searchResults = wrapper.find(SearchResults).first();
should(searchResults.prop('result')).equal(result);
})
})
});
型
我已经很难弄清楚如何使jest.mock
工作,因为它要求变量以mock
为前缀。
但是如果我想测试search
方法的参数,我需要在测试中使用模拟函数。
如果我转换mocking部分,使用变量:
const mockSearch = jest.fn(() => mockPromise)
jest.mock('./search.js', () => {
return { search: mockSearch};
});
型
我得到这个错误:
TypeError:(0,_search.search)不是函数
无论我尝试访问jest.fn
并测试参数,我都无法使其工作。
我做错了什么?
3条答案
按热度按时间jdg4fx2g1#
问题
你得到这个错误的原因与各种操作是如何提升的有关。
即使在你的原始代码中,你只是在 * 为
mockSearch
赋值并调用jest的mock
之后 * 才导入SearchContainer
,规范指出:Before instantiating a module, all of the modules it requested must be available
。因此,当
SearchContainer
被导入,然后又导入search
时,mockSearch
变量仍然是未定义的。有人可能会觉得奇怪,因为这似乎也意味着
search.js
还没有被mocked,所以mocking根本不起作用。幸运的是,(babel-)jest确保将对mock
和类似函数的调用提升到比导入更高的水平,所以mocking将起作用。尽管如此,mock函数引用的
mockSearch
的赋值不会随着mock
调用而提升。因此,相关操作的顺序如下:1.为
./search.js
设置一个模拟工厂1.导入所有依赖项,这将调用一个函数的mock工厂来给予组件
1.为
mockSearch
赋值当第2步发生时,传递给组件的
search
函数将是未定义的,第3步的赋值已经太晚了,无法改变这一点。解决方案
如果您将mock函数创建为
mock
调用的一部分(这样它也会被提升),那么当它被组件模块导入时,它将具有一个有效值,如前面的示例所示。正如你所指出的,当你想让模拟的函数在测试中可用时,问题就开始了。有一个明显的解决方案:单独导入你已经模拟过的模块。
既然你现在知道jest mocking实际上发生在导入之前,一个简单的方法是:
字符串
实际上,您可能需要替换:
型
有:
型
这应该不会造成任何功能上的差异,但可能会使您正在做的事情更加明确(并且应该帮助任何使用类型检查系统(如Flow)的人,因此它不会认为您正在尝试在原始
search
上调用模拟函数)。附加说明
只有当你需要模拟的是模块本身的默认导出时,所有这些才是绝对必要的。否则(正如@publicJorn所指出的),你可以简单地在测试中重新分配特定的相关成员,如下所示:
型
k7fdbhmy2#
在我的例子中,我得到这个错误是因为我没有正确地实现mock。
我的失败代码:
第一个月
当它应该是一个箭头功能时...
jest.mock('react-native-some-module', () => mockedModule);
个eqzww0vc3#
当用响应模拟一个API调用时,记得要使用bloc()=>你的测试并等待 Package 器更新。我的页面做了典型的componentDidMount => make API call => positive response set some state...然而 Package 器中的状态没有得到更新... bloc和await修复了这个问题...这个例子是为了简洁...
字符串