簡體   English   中英

在導入依賴項之前開玩笑模擬 window object

[英]Jest mock window object before importing a dependency

在導入依賴項之前,我需要在 window object 中設置一個值。 說我有這個代碼

// 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 的回答,我收到以下錯誤

  ● 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)

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
  })
})

正如其他答案所指出的,如果myValue是 window 的現有“系統”屬性之一,例如window ,您可能必須window.location其刪除。 刪除的時候不要忘記備份,以便測試后清理時可以恢復。

嘗試將值分配給global.window

像這樣的東西:

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

這可以在jest.setup.js中完成,但您也可以在foo.test.js中定義值

通過創建setup.js ,我能夠在 window object 上的 append 屬性:

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

並在我的jest.config.js文件中的setupFilesAfterEnv中設置文件:

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

我已經用jest.mock解決了這樣的問題:因為它被提升到 import 語句之上,所以可以在導入實際模塊之前和之后執行任何代碼。

在我的情況下,我需要測試一些功能並將節點 env 設置為一個不同於“test”的值,並且由於我只需要在導入時進行此替換,因此我在返回實際值之前將其值設置回“test”模塊。 當然,它可能會因用例而異——這只是在導入完成之前和之后執行代碼的示例。 我還嘗試對特定模塊字段使用吸氣劑,它也有效。

import ApiBase from "../ApiBase";

jest.mock('../ApiBase', () => {
    process.env.NODE_ENV = '';
    const actual = jest.requireActual('../ApiBase');
    process.env.NODE_ENV = 'test';
    return actual;
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM