在导入依赖项之前开玩笑地模拟窗口对象

时间:2020-06-08 15:24:31

标签: javascript unit-testing jestjs

在导入依赖项之前,我需要在window对象中设置一个值。说我有这个代码

// foo.test.js
import { dependency } from './foo'

describe('...', () => {
  it('...', () => {
    // use dependency
  })
})

但是要导入依赖项,我需要在window.myValues

中定义一个值
// foo.js
export const dependency = {
  key: window.myValue.nestedValue
}

由于window.myValue.nestedValue试图访问未定义的属性nestedValue,因此导入文件时,该代码将给我一个错误。

我该怎么办?

修改 在下面的christianeide's answer之后,出现以下错误

  ● Test suite failed to run

    TypeError: Cannot convert undefined or null to object

      2 |   delete global.window.myValue
      3 |   global.window = Object.create(window)
    > 4 |   global.window.myValue = {
        |                 ^
      5 |     nestedValue: 'someValue'
      6 |   }
      7 | }

      at module.exports (jest.setup.js:4:17)
      at node_modules/@jest/core/build/runGlobalHook.js:82:17
      at ScriptTransformer.requireAndTranspileModule (node_modules/@jest/transform/build/ScriptTransformer.js:684:24)
      at node_modules/@jest/core/build/runGlobalHook.js:72:27
      at pEachSeries (node_modules/p-each-series/index.js:8:9)
      at async _default (node_modules/@jest/core/build/runGlobalHook.js:58:5)
      at async runJest (node_modules/@jest/core/build/runJest.js:345:5)

3 个答案:

答案 0 :(得分:1)

es6 导入是“提升”的,这意味着您在代码中的任何地方编写它们,它们都会在导入模块执行之前得到处理,因此导入模块总是在导入模块之前执行。在您的情况下,这意味着 foo.js 在 foo.test.js 之前执行,因此即使您在测试中正确模拟 window 的属性,foo.js 也不会看到您的模拟。

在模拟 window 的属性后,您可以通过在测试中使用 require 导入 foo.js 来解决此问题。

// foo.test.js
window.myValue = { nestedValue: MOCK_NESTED_VALUE };

const { dependency } = require('./foo');

describe('...', () => {
  it('...', () => {
    // use dependency
  })
})

正如其他答案所指出的,如果 myValuewindow 的现有“系统”属性之一,例如 window.location,您可能必须先将其删除。删除时不要忘记备份,以便测试后清理时恢复。

答案 1 :(得分:0)

尝试将值分配给global.window

类似这样的东西:

delete global.window.myValue;
global.window = Object.create(window);
global.window.myValue = {
    nestedValue: 'someValue',
};

这可以在jest.setup.js内完成,但是您也可以在foo.test.js内定义值

答案 2 :(得分:0)

我能够通过创建setup.js在窗口对象上附加属性:

global.propertyA = () => {};
global.nestedPropertyB = {
  propertyC: () => {}
};

并在我的setupFilesAfterEnv文件的jest.config.js中设置文件:

module.exports = {
  setupFilesAfterEnv: ['<rootDir>/tests/js/setup.js']
}