dprothero
dprothero

Reputation: 2722

AngularJS - unit tests - using original service from mock of same service?

I am trying to mock the $timeout service, which I know how to do, however, I need to be able to call the ORIGINAL $timeout service from within my mock. However, it just ends up with a stack overflow, recursively calling itself...

describe("myUnitTest", function () {
var $compile;
var $rootScope;
var $window;
var $timeout;

var timerTriggeredCount;

beforeEach(function () {
  module("myModuleBeingTested", function ($provide) {

    $provide.value("$timeout", fakeTimeout);

    function fakeTimeout(func) {
      timerTriggeredCount++;
      return $timeout(func, 1, false); // need this to call the original $timeout service
    }

    fakeTimeout.cancel = function(timer) {
      $timeout.cancel(timer); // need this to call the original $timeout servic
    }

  });

  inject(["$compile", "$rootScope", "$window", "$timeout", function (c, rs, w, t) {
    $compile = c;
    $rootScope = rs;
    $window = w;
    $timeout = t;
  }]);

});

....

Upvotes: 2

Views: 81

Answers (1)

dprothero
dprothero

Reputation: 2722

OK, I got it. I need to use a decorator (see here at the very end of the page):

describe("myUnitTest", function () {
var $compile;
var $rootScope;
var $window;
var $timeout;

var timerTriggeredCount;

beforeEach(function () {
  module("myModuleBeingTested", function ($provide) {

    var fakeTimeoutDecorator = [
      "$delegate", function ($delegate) {
        var oldTimeout = $delegate;
        var fakeTimeout = function (fn, delay, invokeApply) {
          return oldTimeout(function() {
            timerTriggeredCount++;
            fn();
          }, 1, invokeApply);
        };

        for (var prop in oldTimeout) {
          fakeTimeout[prop] = oldTimeout[prop];
        }

        return fakeTimeout;
      }
    ];

    $provide.decorator("$timeout", fakeTimeoutDecorator);

  });

....

Upvotes: 2

Related Questions