Как переопределить значения конфигурации во время выполнения с помощью node-config?
Я хотел бы переопределить некоторые значения во время теста, в частности, установив мои попытки для службы http на 1 (немедленный сбой, без повторов). Наш проект использует node-config
, В соответствии с документами я могу переопределить с NODE_CONFIG
переменная env:
node myapp.js --NODE_CONFIG='{"Customer":{"dbConfig":{"host":"customerdb.prod"}}}'
Ну, я бы предпочел сделать это в моем тесте, но не для всех тестов. Код говорит, что вы можете разрешить мутации конфигурации, установив 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)
4 ответа
Я один из тех, кто поддерживает node-config
, Ваша ошибка в том, что вы использовали require
во второй раз, когда вы должны были использовать importFresh
снова.
Ваше первое использование importFresh() ничего не отличается от require()
будет, потому что это первое использование require()
,
После установки некоторых переменных вы вызываете require()
, который вернет копию config
уже сгенерированы и кэшированы, игнорируя влияние установленных переменных среды.
Вам нужно было только использовать importFresh()
один раз, где вы в настоящее время используете require()
, Это приведет к возвращению "свежей" копии объекта конфигурации, как вы и ожидали.
Просто меняется config
собственность работала на меня. Например:
const config = require( 'config' );
config.httpServices.integration.enrich.retryInterval = 1;
// Do your tests...
UPD: убедитесь, что переопределения сделаны, прежде чем кто-либо позвонит первым config.get()
, поскольку config
Объект становится неизменным, как только любой клиент использует значения через get()
,
Присоединение поздно, но другие ответы не соответствовали стандарту тестирования в моем проекте, поэтому вот что я придумал
TL;DR
Используйте мокасины..
Подробный ответ
node-config использует функцию для получения значений конфигурации. Издеваясь над функцией, вы можете легко изменить любую конфигурацию, которую считаете подходящей.
Моя личная любимая библиотека — 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
// https://stackoverflow.com/a/57017971/1068746
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
функцию), а не обходить ее, обращаясь к полям напрямую.
Лучше создать файл development.json, production.json et test.json в вашей папке config. вам просто нужно настроить NODE_ENV на использование определенного файла. Надеюсь, поможет:)