2015-05-22 4 views
2

У меня есть кусок кода в 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.

+0

Вы имеете в виду вы специально для проверки модульных тестов в 'obj.publicFn'? – Ryan

+0

@minitech: Да, правильно – batman

+0

Какие операции вы делаете, когда это единичный тест? – Ryan

ответ

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... 
Смежные вопросы