【问题标题】:How do you stub private functions when unit testing a revealing module单元测试显示模块时如何存根私有函数
【发布时间】:2016-07-02 17:21:06
【问题描述】:

我一直在构建一个节点模块,它封装了对 GitHub API 的大量调用,并且在我无限的智慧中使用了显示模块模式构建了它,使我的封装函数保持私有并且只公开简单的方法。请看下面的例子:

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(),但是我想存根私有函数,以便测试不会调用 GitHub API。我使用 Mocha 和 Chai 进行测试,使用 Sinon 进行间谍/存根。

任何关于如何存根这些函数的建议,或者如果这是一个不好的模式,我应该如何测试这个模块将不胜感激!

【问题讨论】:

    标签: javascript node.js unit-testing mocha.js sinon


    【解决方案1】:

    由于github 看起来像一个单例,你可以覆盖它的功能:

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

    你必须在测试完成后重置它:

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

    【讨论】:

      【解决方案2】:

      您应该隔离类的有问题的部分并将其模拟出来,而不是存根私有方法。需要模拟或存根私有方法是一种设计味道,IMO,表明该类太大,您应该分离各种关注点。

      在这种情况下,您可以将github API 作为参数传递给init,而不是深入研究类的内部结构,只需提供一个返回静态结果的虚假 API。

      这在您开始测试错误案例时特别有用,因为您的模拟 API 可以抛出适当的错误并允许您仅测试错误处理行为。

      【讨论】:

        【解决方案3】:

        实际上,有很多非常正当的理由可以让您分出私有函数。就像其中有很多逻辑一样,您只想测试该逻辑。要像处理任何其他函数一样存根任何私有函数,然后将 as any 附加到父对象:

        规格.ts:

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

        服务有一个私有函数startTimeoutTimer。将 as any 附加到服务对象告诉 TypeScript 忽略任何类型并假设您可以做到。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-07
          • 2021-07-27
          • 2015-11-09
          • 2021-06-10
          • 1970-01-01
          • 2016-09-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多