[英]How to mock a constant that is a dependency of the service under test?
我正在測試一個名為connect-key.js
的文件。 它有一個名為keyvault-emulator
的依賴項。
文件#1:
// connect-key.js file
const { save, retrieve, init } = require('./keyvault-emulator')
....
....
....
// SOME TESTS
文件#2:
// The keyvault-emulator.js file
const { storageConnectionString } = require('../config')
現在,如何從我的測試文件connect-key.spec.js
storageConnectionString
模擬 storageConnectionString 的值?
我設想這樣的事情:
// The connect-key.spec.js file
const keyvault_emulator = require('../keyvault-emulator');
const spy = jest.spyOn(keyvault_emulator, 'storageConnectionString');
spy.mockReturnValue('');
這是配置文件:
// config.js file
module.exports = {
storageConnectionString: process.env.STORAGE_CONNECTION_STRING || process.env.Storage,
keyVaultName: process.env.KEY_VAULT
}
這是正確的方法嗎? 完成此任務的最佳方法是什么?
mocking internal dependency之前,這個問題需要弄清楚它的意義何在; 因為 Jest 的 mocking 能力有些受限。 由於問題中沒有提到,我個人選擇了一些最好的例子。
為了更容易理解,假設有一個虛構的 function 叫做testFunction()
; 它是一個 function,返回前面提到的storageConnectionString
。
// key.spec.js
const keyvault_emulator = require('../keyvault-emulator');
js.mock('../keyvault-emulator', () => ({
// everything is original, except testFunction
...jest.requireActual('../keyvault-emulator'),
// this supposed to return () => storageConnectionString but it's mocked here.
testFunction: jest.fn(() => 'mocked')
})
// ✅ it works
expect(keyvault_emulator.testFunction()).toEqual('mocked')
// ❌ this fails!
expect(keyvault_emulator.otherFunctionUsingStorageConnectionString())
.toEqual('mocked')
Jest 只能更換一個 function 或 module 。 它不能重新評估代碼。 在這種情況下, config.js
和keyvault-emulator.js
的依賴關系必須與源代碼分離,以簡化測試過程。
// keyvault-emulator.js
// KeyValue emulator has to be restructured to have constructor, or init function
class KeyValueEmulator {
constructor(config) {
this.config = config;
}
testFunction() {
// do something with this.config
return this.config;
}
}
// key.spec.js
const mockedConfig = { storageConnectionConfig: 'mocked' }
const keyValueEmulator = new KeyValueEmulator(mockedConfig);
// ✅ it works
expect(keyValueEmulator.testFunction()).toEqual('mocked')
工作代碼為Github
// key.spec.js
import config from "./config";
jest.mock("./config", () => ({ default: { storageConnectionString: "mocked" } }));
import { storageConnectionString, testFunction } from "./index";
describe("config mocking", () => {
it("value is mocked", () => {
// ✅ it works
expect(config.storageConnectionString).toEqual("mocked");
expect(testFunction()).toEqual("mocked");
});
});
正如案例 2 中已經解釋的那樣,這是不可能的情況。 Jest 不能模擬單個變量; 它可能最接近問題中提到的代碼,這就是需要澄清的原因。
// same as code in the question. the test code should be fixed to work,
// but let's say it's working as you've intended.
// key.spec.js
const keyvault_emulator = require('../keyvault-emulator');
const spy = jest.spyOn(keyvault_emulator, 'storageConnectionString');
spy.mockReturnValue('mocked');
// ✅ it may work...but
expect(keyvault_emulator.storageConnectionString).toEqual('mocked')
// ❌ this fails!
expect(keyvault_emulator.testFunction()).toEqual('mocked')
這是正確的方法嗎? 完成此任務的最佳方法是什么?
就像開發者世界中的許多案例一樣,這取決於案例。 我個人會選擇 2-1 中提到的硬解耦方法用於一般用途,但在很多情況下它並不完全適合。 選擇最適合您的情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.