2016-03-16 2 views
3

Я создаю модуль узла, который обертывает ряд вызовов API GitHub и в моей бесконечной мудрости построил это с использованием шаблона раскрывающего модуля, сохраняя мои функции упаковки частные и только разоблачение простых методов. См. Приведенный ниже пример:Как вы закрываете частные функции при модульном тестировании модуля выявления

github.shortcuts = (function(){ 

    var appPath; 

    var createRepo = function(name){ 
    var deferred = Q.defer(); 
    github.repos.create({ 
     name: name, 
     auto_init: true 
    }, function(error, result){ 
     if (error) { 
     deferred.reject(new Error(error)); 
     } else { 
     deferred.resolve(result); 
     } 
    }); 
    return deferred.promise; 
    }; 

    var updateRef = function(result){ 
    var deferred = Q.defer(); 
    var user = result.user; 
    var repo = result.repo; 
    github.gitdata.updateReference({ 
     user: user, 
     repo: repo, 
     ref: 'heads/master', 
     sha: result.sha 
    }, function(error, result){ 
     if (error) { 
     deferred.reject(new Error(error)); 
     } else { 
     deferred.resolve(result); 
     } 
    }); 
    return deferred.promise; 
    }; 

    return { 
    init: function(token, name, path){ 
     var deferred = Q.defer(); 
     appPath = path; 

     var error = function(error){ 
     return deferred.reject(error); 
     }; 

     github.authenticate({ 
     type: "oauth", 
     token: token 
     }); 

     createRepo(name) 
     .then(updateRef, error) 
     .then(function(result){ 
      deferred.resolve(result); 
     }, error); 

     return deferred.promise; 
    } 
    }; 

})(); 

Тем не менее, для этого я выполняю тесты единицы измерения. Я не хочу проверять свои личные функции, просто публичный init(), однако я бы хотел закрыть отдельные функции, чтобы тест не вызывал API GitHub. Я использую Mocha и Chai для своих тестов и Sinon для своих шпионов/заглушек.

Любые советы о том, как заглушить эти функции или если это плохой шаблон, как еще я должен протестировать этот модуль, будем признательны!

ответ

4

Вы должны изолировать проблемную часть из класса и издеваться над этим, вместо того, чтобы обманывать частные методы. Необходимость издеваться или закрывать частный метод - это запах дизайна, ИМО, указывающий, что класс слишком велик, и вы должны отделить различные проблемы.

В этом случае вы можете передать API github в качестве параметра init и вместо того, чтобы копать внутренние компоненты вашего класса, просто предоставить поддельный API, который возвращает статические результаты.

Это особенно полезно, если вы начинаете тестировать ошибки, так как ваш mock API может выбросить соответствующую ошибку и позволить вам только протестировать поведение обработки ошибок.

1

С github выглядит как одноточечного вы можете переопределить его функции:

github.gitdata.updateReference = sinon.stub().return(Promise.resolve([])); 

И вы должны сбросить его после того, как тест проводится:

afterAll(() => { 
github.gitdata.updateReference.reset(); 
}); 
0

На самом деле существует множество очень веских причин, по которым вы захотите выдать частную функцию. Как и в этом много логики, и вы хотите проверить именно эту логику. Для того, чтобы погасить окурок любая частная функция заглушки его, как вы бы любой другой функции, а затем прикрепить as any к родительскому объекту:

Spec.ts:

startTimeoutTimerSpy = spyOn(service as any, 'startTimeoutTimer'); 

служба имеет закрытую функцию startTimeoutTimer. Прикрепление as any к объекту службы говорит TypeScript игнорировать любые типизации и просто предположим, что вы можете это сделать.

Смежные вопросы