【问题标题】:How do I override config values at runtime with node-config?如何在运行时使用 node-config 覆盖配置值?
【发布时间】:2017-09-22 16:59:36
【问题描述】:

我想在测试时覆盖一些值,特别是将我的 http 服务重试次数设置为 1(立即失败,不重试)。我们的项目使用node-config。根据docs,我可以用NODE_CONFIG env 变量覆盖:

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 代码库)

【问题讨论】:

    标签: node.js testing configuration lab node-config


    【解决方案1】:

    我是node-config 的维护者之一。你的错误是你第二次使用require,而你应该再次使用importFresh

    您第一次使用“importFresh()”与require() 没有什么不同,因为它是第一次使用require()

    设置一些变量后,调用require(),它将返回已经生成并缓存的config的副本,忽略设置的环境变量的影响。

    您只需要使用一次importFresh(),而您目前使用的是require()。如您所料,这将导致返回配置对象的“新”副本。

    【讨论】:

    • 那行得通。我现在明白为什么了,看了之后。不过,您的回答可能需要更多解释。
    【解决方案2】:

    只需更改config 的属性对我有用。 例如:

    const config = require( 'config' ); 
    
    config.httpServices.integration.enrich.retryInterval = 1;
    
    // Do your tests...
    

    UPD:确保在任何人调用第一个 config.get() 之前完成覆盖,因为只要任何客户端通过 get() 使用这些值,config 对象就会变得不可变。

    【讨论】:

      【解决方案3】:

      加入晚了,但其他答案不符合我项目中的测试标准,所以这是我想出的

      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
                  // 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 函数),而不是通过直接访问字段来绕过它。

      【讨论】:

        【解决方案4】:

        最好在您的配置文件夹中创建一个 development.json、production.json 和 test.json,node-config 将使用它您的应用程序配置。 您只需将 NODE_ENV 设置为使用特定文件即可。 希望对你有帮助:)

        【讨论】:

        • 并非如此。我希望能够在特定测试中更改我的配置,而不是针对所有测试。正如我所提到的:“我更愿意在我的测试中这样做,但不是在所有测试中都这样做。”
        • @jcollum 好的,我明白了。您是否尝试过导出配置,例如 export NODE_CONFIG='{"Customer":{"dbConfig":{"host":"customerdb.prod"}}}'
        • 你读过我的源代码吗?它似乎回答了你的问题。
        • 我的意思是在你的 .bashrc / .bash_profile 上导出它,而不是通过添加 --NODE_CONFIG
        • 但这意味着我要为所有测试设置它。或者我必须对每个配置进行单独的 NPM 测试调用。这不是最佳选择。
        猜你喜欢
        • 2019-08-29
        • 2011-06-02
        • 2023-01-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多