如何使用依赖注入进行测试?

时间:2015-05-22 04:17:04

标签: javascript dependency-injection

我在js中有这样的代码:

var obj = (function(){
   var stateObj = {key:"privateValue"};
   return {
       getState: function() {
            return stateObj.key;
       },
       publicFn : function(){
            //do some operation with stateObj
            if(getState() == "test") {
                 //. . . . 
            }
       }
   }
}());

我测试了这样的代码:

//test case
sandbox.stub(obj.getState,"test")
assertItShouldGoInsideIfLoop(obj.publicFn())

然而,在代码审查中,我的团队主管说,这是错误的,他让我使用依赖注入来处理这些情况。

我真的不知道为什么上述方法是错误的,甚至为什么要使用DI。

1 个答案:

答案 0 :(得分:2)

如果我正确地解释了这一点,那么问题在于您对调用publicFn的价值的测试取决于stateObj的值。依赖注入背后的整个想法是,您提供了一些方法来在测试中提供这些值,以便将数据与被测函数的行为分离。

var obj = (function(){
   return {
       setStateObj: function(stateObj) {
           this.stateObj = stateObj;
       },
       getState: function() {
            return this.stateObj.key;
       },
       publicFn : function(){
            //do some operation with stateObj
            if(getState() == "test") {
                 //. . . . 
            }
       }
   }
}());

现在我们可以使用setStateObj在测试中根据需要设置状态,而不是存储值,这可能是危险的:

obj.setStateObj({ key: 'test' })
assertItExecutesIfStatement(obj.publicFn())

obj.setStateObj({ key: 'blah' })
assertItDoesntExecuteIfStatement(obj.publicFn())

那为什么选择短信getState?假设我们评论getState

的内容
       getState: function() {
            // return this.stateObj.key;
       }, // returns nothing, but you're stubbing it to return "test" anyway!

显然,这个功能不起作用,但是对你的存根来说,它会!因此,尽管有非工作代码,你仍然可以通过测试!

这是另一个为依赖注入提供另一个案例的例子。说我有以下功能:

function getDayOfWeek() {
  var date = new Date();
  var dayNames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
  return dayNames[date.getDay()];
}

getDayOfWeek功能取决于date。这将是一个噩梦,因为我们无法控制date的价值。如果我们用提供日期值的方式重写此函数(即注入依赖项),我们可以轻松地检查函数的任何固定日期:

function getDayOfWeek(date) {
  date = date || new Date();
  var dayNames = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
  return dayNames[date.getDay()];
}

assertEqual('Wednesday', getDayOfWeek(new Date(2015, 0, 1)));
assertEqual('Thursday', getDayOfWeek(new Date(2015, 0, 2)));
// and so on...