我希望当我使用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 () { ... }
}
答案 0 :(得分:0)
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!
});
});