[英]Mocking environment and/or exported constants in Jest for Node apps
我在一個 express 應用程序中有一個模塊,我試圖測試它使用從模塊導出的常量。 許多這些常量來自環境變量。
// src/constants.js
export default {
ID_SOURCE: process.env.ID_SOURCE,
ID_PROVIDER: process.env.ID_PROVIDER
};
/*
process.env {
ID_SOURCE: 'foo',
ID_PROVIDER: 'bar'
}
*/
這是在被測模塊中獲取這些常量的模式。
import constants from './constants';
import { errors } from './errors';
const { ID_SOURCE, ID_PROVIDER } = constants;
export const moduleUnderTest = async (req, res) => {
if (!ID_SOURCE || !ID_PROVIDER) {
if (!ID_SOURCE) logService('ID_SOURCE not provided');
if (!ID_PROVIDER) logService('ID_PROVIDER not provided');
throw { err: errors.unexpectedError };
};
// ... do stuff
return res.status(200).json({ cool: 'beans' });
}
我想測試不存在環境變量的異常場景。 在模塊中的當前模式下,這已被證明是困難的,因為即使我模擬環境,模塊也會在環境更改之前被評估——並且模塊中的ID_SOURCE
和ID_PROVIDER
常量被初始化。
重要的是,我只想更改ONE TEST的常量。 這是我嘗試過的。
import constants from './constants';
import { moduleUnderTest } from './moduleUnderTest';
describe('Test module', () => {
beforeEach(() => {
jest.clearAllMocks();
})
test('test exception scenario', async () => {
jest.doMock('./constants', () => {
const actualConstants = jest.requireActual('./constants');
return {
__esModule: true,
...actualConstants,
ID_SOURCE: undefined,
ID_PROVIDER: undefined
}
});
// ... assume req/res are available
try {
await moduleUndertest(req, res);
} catch(ex) {
// by the time we get here, the variables are set from the environment still
// because the module was evaluated and ID_SOURCE and ID_PROVIDER variables in the closure set
// before mocking the constants
expect(ex.message).toBeDefined();
}
});
由於上述評論中所述的原因,模擬環境也不起作用......模塊在導入時進行評估,並且在模擬更改它們之前從環境中初始化這些變量。
ID_SOURCE
和ID_PROVIDER
始終具有從環境分配給它們的值。
當然,一個明顯的解決方案是從函數定義中的常量中訪問變量,這些變量只會在調用時執行……但問題是,在我使用這種模式的代碼庫中,我使用的是EVERYWHERE 。 我不能隨便開始任意重構一切來讓這個工作,我覺得必須有更好的方法。
我也嘗試過mocked-env
,但由於與上述相同的原因而失敗。 我試過在beforeEach
鈎子中調用jest.resetModules
並在每個測試中的模塊中調用,但這種模式到目前為止還沒有產生任何結果。 如果是這樣的話,我有興趣了解更多關於這種模式的信息。
我認為使用 jest setupFiles 的方法可能是解決方案,因為我在其他情況下使用它們,在這些情況下,環境變量需要在本地(隨處)可用,但不存在,但我不希望每次測試都在全局范圍內模擬這些...只有一項測試。
在我的 Jest 配置中,我添加了一個包含我為測試定義的環境的文件。
setupFiles: [
'<rootDir>/src/.env.testing.js',
],
在這個文件中,我然后設置我使用的環境:
process.env.PORT='9999';
然后我讓我的正常服務根據需要從環境中讀取配置。 你可以為 setupFiles 使用任何文件名,我正在復制我對 .env 文件的使用。
最終,這就是我為修復它所做的。
test('should process exception', async () => {
jest.resetModules(); // clear require.cache
jest.doMock('../src/constants', () => {
const constants = jest.requireActual('../src/constants');
console.log(constants);
return {
__esModule: true,
default: {
...constants,
ID_SOURCE: 'foo'
}
}
});
const req = makeReq({ session: { email: "foo@bar.com" }});
const res = makeRes();
const { updateUserProfile } = await import(
"../src/controller"
);
await updateUserProfile(req, res);
expect(res.status).toHaveBeenCalledWith(500);
})
最大的問題之一是確保在模擬常量文件之前清除 require 緩存。 然后,這只是在我模擬了常量模塊之后動態導入被測模塊的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.