Как переопределить значения конфигурации во время выполнения с помощью 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 на использование определенного файла. Надеюсь, поможет:)

Другие вопросы по тегам