Jest 模拟 window.location 方法
当你要在 jest
中 mock
window.location
时,你可能会这么做
it('mocks and calls window.location.reload', () => {
window.location.reload = jest.fn();
window.location.reload();
expect(window.location.reload).toHaveBeenCalled();
});
当你运行这个测试的时候,它的运行结果是失败的
使用 jest.spyon
方法
基于这个方法可以通过测试
// window.location.reload = jest.fn();
jest.spyOn(window.location, 'reload');
但在日志中有打印出来的错误信息
console.error node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Not implemented: navigation (except hash changes)
发生这种情况是因为 jsdom 试图使该方法的行为与其浏览器的表现一样。但是,测试在Node.js 中运行。
使用 Mock 方法
要消除错误,location.reload
需要在分配给 mock
之前进行 配置
Object.defineProperty(window.location, 'reload', {
configurable: true,
});
window.location.reload = jest.fn();
这次运行测试时,它应该*通过并且没有错误。
jsdom 14+ 更新
不幸的是,这不再适用于 jsdom >=14。
新的解决方案是删除 location
并重新创建 reload
为 mock
:
delete window.location;
window.location = { reload: jest.fn() };
最终解决方案
describe('window.location', () => {
const { location } = window;
beforeAll(() => {
delete window.location;
window.location = { reload: jest.fn() };
});
afterAll(() => {
window.location = location;
});
it('mocks `reload`', () => {
expect(jest.isMockFunction(window.location.reload)).toBe(true);
});
it('calls `reload`', () => {
window.location.reload();
expect(window.location.reload).toHaveBeenCalled();
});
});
针对 TypeScript
的报错,处理如下
delete (window as any).location;
window.location = { replace: jest.fn() } as any as Location;