在Jest中模拟全局变量window

16

我有一个能在Node和浏览器中运行的函数,希望用jest测试:

const myFn = () => {
  if(typeof window !== 'object'){
     return 1;
  }
  return 2;
}

我该如何将全局的 window 对象设置为 undefined,以便测试 node 分支,并返回 1。

例如:

  test('myTest', ()=> {
      global.window = undefined;
      expect(myFn()).toEqual(1); // result: 2
  });

我尝试了这里的建议,但没有成功:在Jest中模拟全局变量


这个回答解决了你的问题吗?如何使用Jest模拟JavaScript的'window'对象? - Michael Freidgeim
2个回答

15

你可以尝试使用自 Jest 20.0.0 起可用的 @jest-environment 文档块来为不同的测试更改环境。默认情况下,它使用 jsdom,但你可以将其改为使用 node。以下是他们文档中的摘录:

/**
 * @jest-environment jsdom
 */

test('use jsdom in this test file', () => {
  const element = document.createElement('div');
  expect(element).not.toBeNull();
});

参考:https://facebook.github.io/jest/docs/en/configuration.html#testenvironment-string


6
非常感谢 @nbkhope。还有一件需要注意的事情是,(针对我的示例),这个注释块必须在任何导入语句之前就声明在文件顶部。这显然意味着设置环境变量将适用于该文件中的所有测试。您无法为单个测试应用环境变量,比如在描述块内。 - Daniel Billingham
感谢@DanielBillingham,我最初在文档中错过了这一点。将测试分为两个单独的文件并不理想,但我不能抱怨太多,因为设置非常容易。 - Tetraodon
@nbkhope,我尝试了上面的方法,但在使用React测试库时没有起作用,有什么办法可以实现吗?https://stackoverflow.com/questions/59173156/making-the-window-to-different-data-type-in-react-testing-library - Learner

3

使用新版本的jsdom,您可以执行以下操作:

import { JSDOM } from 'jsdom';

let windowSpy: any;
beforeEach(() => {
  windowSpy = jest.spyOn(global as any, 'window', 'get');
});
afterEach(() => {
  windowSpy.mockRestore();
});

describe('', () => {
  it ('', () => {
    const { window } = new JSDOM();
    windowSpy.mockImplementation(() => window);
    // now you have `window` in test environment
  });
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接