8

我想在测试时覆盖一些值,特别是将我的 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

4 回答 4

7

我是node-config. 您的错误是require您应该importFresh再次使用的第二次使用。

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

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

您只需importFresh()在当前使用的地方使用一次require(). 如您所料,这将导致返回配置对象的“新”副本。

于 2017-09-22T17:28:19.827 回答
3

简单地改变config的财产对我有用。例如:

const config = require( 'config' ); 

config.httpServices.integration.enrich.retryInterval = 1;

// Do your tests...

UPD:确保在任何人调用 first 之前完成覆盖config.get(),因为config一旦任何客户端通过get().

于 2018-10-11T10:41:09.913 回答
1

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

TL;博士

使用模拟..

详细解答

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

于 2022-01-21T23:36:00.740 回答
0

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

于 2017-09-22T17:07:03.607 回答