如何在运行时使用节点配置覆盖配置值?
How do I override config values at runtime with node-config?
我想在测试时覆盖一些值,特别是将 HTTP 服务的重试次数设置为 1(立即失败,不重试)。我们的项目使用 node-config
。根据 docs 我可以用 NODE_CONFIG
环境变量覆盖:
node myapp.js --NODE_CONFIG='{"Customer":{"dbConfig":{"host":"customerdb.prod"}}}'
好吧,我更愿意在我的测试中这样做,但不是对所有测试。 code 表示您可以通过设置 ALLOW_CONFIG_MUTATIONS
来允许配置更改。
process.env.ALLOW_CONFIG_MUTATIONS = "true";
const importFresh = require('import-fresh');
importFresh("config");
process.env.NODE_CONFIG = JSON.stringify({httpServices:{integration:{enrich: {retryInterval: 1, retries: 1}}}});
expect(process.env.NODE_CONFIG, 'NODE_CONFIG not set').to.exist();
expect(process.env.NODE_CONFIG, 'NODE_CONFIG not set').to.match(/retryInterval/);
expect(process.env.ALLOW_CONFIG_MUTATIONS, 'ALLOW_CONFIG_MUTATIONS not set').to.equal("true");
const testConfig = require("config");
console.dir(testConfig.get("httpServices.integration.enrich"));
expect(testConfig.get("httpServices.integration.enrich.retryInterval"), 'config value not set to 1').to.equal(1);
结果:
{ url: 'https://internal-**********',
retryInterval: 5000,
retries: 5 }
`Error: config value not set to 1: Expected 5000 to equal specified value: 1`
如何让这个覆盖生效?
(预计来自Hapi.js代码库)
最好在您的配置文件夹中创建一个 development.json、production.json 和 test.json,node-config 将使用它作为您的应用程序配置。
您只需将 NODE_ENV 设置为使用特定文件即可。
希望对您有所帮助:)
我是 node-config
的维护者之一。你的错误是你第二次使用 require
而你应该再次使用 importFresh
。
您第一次使用 "importFresh()" 与 require()
没有什么不同,因为这是第一次使用 require()
。
设置一些变量后,调用require()
,这将return已经生成并缓存的config
副本,忽略环境变量设置的影响。
您只需要使用一次 importFresh()
,而您目前使用的是 require()
。如您所料,这将导致配置对象的 "fresh" 副本被 returned。
简单地改变 config
的 属性 对我有用。
例如:
const config = require( 'config' );
config.httpServices.integration.enrich.retryInterval = 1;
// Do your tests...
UPD:确保在任何人调用第一个 config.get()
之前完成覆盖,因为只要任何客户端通过 get()
使用值,config
对象就会变得不可变。
加入晚了,但其他答案不符合我项目中的测试标准,所以这是我想出的
TL;DR
使用模拟..
详细解答
node-config 使用函数 get
获取配置值。
通过模拟函数 get
你可以轻松修改任何你认为合适的配置..
我个人最喜欢的库是 sinon
这是一个用 sinon
模拟的实现
const config = require('config');
const sinon = require('sinon');
class MockConfig {
constructor () {
this.params = {};
this.sandbox = sinon.sandbox.create();
}
withConfValue (confKey, confValue) {
this.params.confValues[confKey] = confValue;
return this;
}
reset () {
this.params.confValues: {};
return this;
}
restore() {
this.sandbox.restore();
}
apply () {
this.restore(); // avoid duplicate wrapping
this.sandbox.stub(config, 'get').callsFake((configKey) => {
if (this.params.confValues.hasOwnProperty(configKey)) {
return this.params.confValues[configKey];
}
// not ideal.. however `wrappedMethod` approach did not work for me
//
return configKey
.split('.')
.reduce((result, item) => result[item], config)
});
}
}
const instance = new MockConfig();
MockConfig.instance = () => instance;
module.exports = MockConfig;
用法是
const mockConfig = require('./mock_config').instance();
...
beforeEach(function () {
mockConfig.reset().apply();
})
afterEach(function () {
mockConfig.reset().clear();
})
it('should do something') {
mockConfig.withConfValue('some_topic.some_field.property', someValue);
... rest of the test ...
}
假设
此方法的唯一假设是您遵循 node-config 读取配置的方式(使用 get
函数),而不是通过直接访问字段来绕过它。
我想在测试时覆盖一些值,特别是将 HTTP 服务的重试次数设置为 1(立即失败,不重试)。我们的项目使用 node-config
。根据 docs 我可以用 NODE_CONFIG
环境变量覆盖:
node myapp.js --NODE_CONFIG='{"Customer":{"dbConfig":{"host":"customerdb.prod"}}}'
好吧,我更愿意在我的测试中这样做,但不是对所有测试。 code 表示您可以通过设置 ALLOW_CONFIG_MUTATIONS
来允许配置更改。
process.env.ALLOW_CONFIG_MUTATIONS = "true";
const importFresh = require('import-fresh');
importFresh("config");
process.env.NODE_CONFIG = JSON.stringify({httpServices:{integration:{enrich: {retryInterval: 1, retries: 1}}}});
expect(process.env.NODE_CONFIG, 'NODE_CONFIG not set').to.exist();
expect(process.env.NODE_CONFIG, 'NODE_CONFIG not set').to.match(/retryInterval/);
expect(process.env.ALLOW_CONFIG_MUTATIONS, 'ALLOW_CONFIG_MUTATIONS not set').to.equal("true");
const testConfig = require("config");
console.dir(testConfig.get("httpServices.integration.enrich"));
expect(testConfig.get("httpServices.integration.enrich.retryInterval"), 'config value not set to 1').to.equal(1);
结果:
{ url: 'https://internal-**********',
retryInterval: 5000,
retries: 5 }
`Error: config value not set to 1: Expected 5000 to equal specified value: 1`
如何让这个覆盖生效?
(预计来自Hapi.js代码库)
最好在您的配置文件夹中创建一个 development.json、production.json 和 test.json,node-config 将使用它作为您的应用程序配置。 您只需将 NODE_ENV 设置为使用特定文件即可。 希望对您有所帮助:)
我是 node-config
的维护者之一。你的错误是你第二次使用 require
而你应该再次使用 importFresh
。
您第一次使用 "importFresh()" 与 require()
没有什么不同,因为这是第一次使用 require()
。
设置一些变量后,调用require()
,这将return已经生成并缓存的config
副本,忽略环境变量设置的影响。
您只需要使用一次 importFresh()
,而您目前使用的是 require()
。如您所料,这将导致配置对象的 "fresh" 副本被 returned。
简单地改变 config
的 属性 对我有用。
例如:
const config = require( 'config' );
config.httpServices.integration.enrich.retryInterval = 1;
// Do your tests...
UPD:确保在任何人调用第一个 config.get()
之前完成覆盖,因为只要任何客户端通过 get()
使用值,config
对象就会变得不可变。
加入晚了,但其他答案不符合我项目中的测试标准,所以这是我想出的
TL;DR
使用模拟..
详细解答
node-config 使用函数 get
获取配置值。
通过模拟函数 get
你可以轻松修改任何你认为合适的配置..
我个人最喜欢的库是 sinon
这是一个用 sinon
模拟的实现const config = require('config');
const sinon = require('sinon');
class MockConfig {
constructor () {
this.params = {};
this.sandbox = sinon.sandbox.create();
}
withConfValue (confKey, confValue) {
this.params.confValues[confKey] = confValue;
return this;
}
reset () {
this.params.confValues: {};
return this;
}
restore() {
this.sandbox.restore();
}
apply () {
this.restore(); // avoid duplicate wrapping
this.sandbox.stub(config, 'get').callsFake((configKey) => {
if (this.params.confValues.hasOwnProperty(configKey)) {
return this.params.confValues[configKey];
}
// not ideal.. however `wrappedMethod` approach did not work for me
//
return configKey
.split('.')
.reduce((result, item) => result[item], config)
});
}
}
const instance = new MockConfig();
MockConfig.instance = () => instance;
module.exports = MockConfig;
用法是
const mockConfig = require('./mock_config').instance();
...
beforeEach(function () {
mockConfig.reset().apply();
})
afterEach(function () {
mockConfig.reset().clear();
})
it('should do something') {
mockConfig.withConfValue('some_topic.some_field.property', someValue);
... rest of the test ...
}
假设
此方法的唯一假设是您遵循 node-config 读取配置的方式(使用 get
函数),而不是通过直接访问字段来绕过它。