我期望当我使用jest.mock()
模拟一个模块并将函数实现传递给每个对象时,它们会继续进行测试。
import * as services from '_services';
// I thought this would be enough to mock 'load_basket'
jest.mock('_services', () => ({
load_basket: jest.fn(() => Promise.resolve([]))
}));
describe('WB Component', () => {
it('loads basket if basket prop is null', () => {
// However, if I don't use .mockImplemenation here it gives
// me an error that load_basket wasn't called
const spy = spyOn(services, 'load_basket').mockImplementation(() => Promise.resolve([]));
const wrapper = shallow(<WB basket={null} />);
expect(spy).toHaveBeenCalled();
wrapper.unmount();
spy.mockRestore();
});
});
但我可以删除.mock
中的函数实现,只有load_basket: jest.fn()
,但我不能删除底部的.mockImplementation(() => Promise.resolve([]))
或我会得到expected spy to have been called, but it was not called
。
编辑:如果我在原始的.mock
调用或.mockImplementation
中既没有函数实现,它也会给我一个TypeError: Cannot read property 'then' of undefined
... load_basket是'undefined'。这对我来说很有意义,但我仍然不明白为什么在.mock
中嘲弄这个函数会使它与测试中的间谍函数不同?
Edit2:load_basket
以下列方式使用
class WB extends Component {
constructor(props) {
super(props);
this.state = {
basket: props.basket,
loading_basket: !props.basket,
};
}
componentDidMount(): void {
if (!this.state.basket) {
load_basket()
.then(res => {
this.setState({
basket: res,
loading_basket: false
});
})
.catch( ... );
}
}
render () { ... }
}
jest.mock
接受一个可选的factory
参数,如果提供了一个,那么module
将替换为调用factory
参数的结果。
因此,当你的测试函数被调用时,services.load_basket
已经是一个mock function了。
错误详情
你正在调用spyOn
,最终调用undocumented legacy Jasmine
spyOn
function(Jest
基于Jasmine
),我猜你打算打电话给jest.spyOn
。
来自spyOn
的Jasmine
函数与Jest
模拟函数无法正常工作,如果您还没有模拟实现,最终会导致您看到的错误。
请注意,如果你调用了jest.spyOn
它只会return the existing mock function,因为load_basket
已经是一个模拟函数,它可以在没有模拟实现的情况下工作。
尽管如此,你不需要监视services.load_basket
,因为它已经是一个模拟函数。
您的测试可以简化为:
import * as services from '_services';
jest.mock('_services', () => ({
load_basket: jest.fn(() => Promise.resolve([]))
}));
describe('WB Component', () => {
it('loads basket if basket prop is null', () => {
const wrapper = shallow(<WB basket={null} />);
expect(services.load_basket).toHaveBeenCalled(); // Success!
});
});