如何模拟被测试服务的依赖项常量?



我正在测试一个名为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的值?

我的设想是这样的:

// 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

在嘲弄内部依赖之前,问题需要澄清它的意义是什么;因为杰斯特的嘲讽能力是有限的。由于问题中没有提到,我个人选择了一些最好的例子。

为了更容易理解,假设有一个虚函数testFunction();它是一个返回前面提到的storageConnectionString的函数。

<标题>1。仅适用于测试范围内的特定功能,不适用其他功能。
// 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')
<标题>

2。对于模块中的所有内容Jest只能替换函数或模块. 它不能重新计算代码。在这种情况下,config.jskeyvault-emulator.js的依赖性必须从源解耦,以简化测试过程。

2 - 1。从源本身硬解耦。

// 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')

2 - 2。与jest的内部模块mock进行软解耦。

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");
});
});
<标题>

3。模拟单个变量正如在情形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中提到的硬解耦方法用于一般用途,但在许多情况下它并不完全适合。选择一个最适合你的案例。

最新更新