是否有可能窥探或嘲笑“幕后”变量的价值?

时间:2015-03-18 14:14:48

标签: javascript unit-testing karma-jasmine sinon

让我们说我的代码修改了一个未向用户公开的变量,如下所示:

var model;

module.exports = {
  doSomething: function() {
    ...
    //at some point in the code, modify model
    if(/* something happened */) {
      model = '123';
    },
    doSomethingElse: function() {
      //use model in some way
    }
  }
};

如果我以后想要编写单元测试以确保model已更新,但我没有获取它,我该如何测试呢?这可能与Karma / Jasmine / Sinon.js有关吗?

2 个答案:

答案 0 :(得分:0)

直接检查模型值是不可能的,因为它隐藏在闭包中。

你仍然可以为它编写测试:你的“模型”会使doSomethingElse表现不同。调用doSomething后,您可以验证它是否符合您的期望。这样,您也可以自由重构模块的内部,而无需更改测试用例。

答案 1 :(得分:0)

通常,测试私有方法或属性是反模式。通过将实现的各个方面设为私有,您可以明确地创建自由,以便在不更改公共API的情况下更改这些实现详细信息的工作方式。

因此,在一个理想的世界中,你不应该(在这种情况下,你不能)测试model值。

尽管如此,我们并不总是生活在一个理想的世界里。因此,如果你真的必须测试私有属性和方法,你可以考虑一些变通方法。

首先,您可以查找环境变量,并导出其他属性(通过将它们附加到exports)。

var model;
module.exports = {
  ...
}
if(process.env.ENV === 'TEST') {
  module.exports.model = model;
}

第二,您可以使用约定而不是将内容完全隐私。例如,一个常见的约定是使用_为私有实体添加前缀,以表示它们不是公共API的一部分。根据将使用您的API的受众群体,这可能会有不同程度的有效性。

第三,您可以为私有变量创建访问器,并以某种方式检查测试环境的存在(可能是全局变量,环境变量或注入模块的变量)在实例化时)只允许在检测到测试环境时进行访问。

第四,您可以允许将“督察”对象注入您的模块(此对象仅在测试期间出现)。我使用这种模式取得了一些成功。

module.exports = function(spies) {
   ...
   spies = spies || {};
   var model = spies.model;
   ...
}
...
// instantiate the module in the test
var spies = {};
var mock = new Module(spies);
// do a thing
expect(spies.model).to.eql("foo");

但实际上,您应该重新考虑您的测试策略和设计。