Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you stub private functions when unit testing a revealing module

I have been building a node module that wraps a number of calls to the GitHub API and in my infinite wisdom have built this using the revealing module pattern, keeping my wrapping functions private and only exposing simple methods. See the example below:

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;
    }
  };

})();

However writing unit tests for this is causing me issues. I don't want to test my private functions, just the public one init(), however I would want to stub the private functions so that the test will not call to the GitHub API. I am using Mocha and Chai for my tests and Sinon for my spys/stubs.

Any advice on how to stub these functions or if this is a bad pattern, how else I should test this module would be appreciated!

like image 875
oligibson Avatar asked Mar 16 '16 17:03

oligibson


1 Answers

Actually there are a bunch of very valid reasons that you would want to sub out a private function. Like there is a lot of logic in it and you want to test out just that logic. To stub out any private function stub it out like you would any other function, then attach as any to the parent object:

Spec.ts:

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

service has a private function startTimeoutTimer. Attaching the as any to the service object tells TypeScript to ignore any typings and just assume you can do it.

like image 156
Samuel Thompson Avatar answered Oct 05 '22 09:10

Samuel Thompson