4

The scenario is I have a ChildCtrl controller that inherits from BaseCtrl following this inheritance pattern:

angular.module('my-module', [])
    .controller('BaseCtrl', function ($scope, frobnicate) {
        console.log('BaseCtrl instantiated');

        $scope.foo = frobnicate();

        // do a bunch of stuff
    })

    .controller('ChildCtrl', function ($controller, $scope) {
        $controller('BaseCtrl', {
            $scope: $scope,
            frobnicate: function () {
                return 123;
            }
        });
    });

Assuming BaseCtrl does a bunch of stuff and is already well tested, I want to test that ChildCtrl instantiates BaseCtrl with certain arguments. My initial thought was something along these lines:

describe("ChildCtrl", function () {
    var BaseCtrl;

    beforeEach(module('my-module'));

    beforeEach(module(function($provide) {
        BaseCtrl = jasmine.createSpy();
        $provide.value('BaseCtrl', BaseCtrl);
    }));

    it("inherits from BaseCtrl", inject(function ($controller, $rootScope) {
        $controller('ChildCtrl', { $scope: $rootScope.$new() });

        expect(BaseCtrl).toHaveBeenCalled();
    }));
});

However when I run the test the spy is never called and the console shows "BaseCtrl instantiated", indicating that $controller is using the actual controller instead of the instance I am providing with $provide.value().

What's the best way to test this?

Community
  • 1
  • 1
Michael Kropat
  • 14,557
  • 12
  • 70
  • 91

1 Answers1

5

So it looks like $controller doesn't search for controllers by name in the $provide.value() namespace. Instead you have to use the $controllerProvider.register() method, which is only accessible from the module.config() block. Fortunately it looks like there's a hook we can use to get access to $controllerProvider on the module under test.

The updated test code looks like:

describe("ChildCtrl", function () {
    var BaseCtrl;

    beforeEach(module('my-module', function ($controllerProvider) {
        BaseCtrl = jasmine.createSpy();
        BaseCtrl.$inject = ['$scope', 'frobnicate'];

        $controllerProvider.register('BaseCtrl', BaseCtrl);
    }));

    beforeEach(inject(function ($controller, $rootScope) {
        $controller('ChildCtrl', { $scope: $rootScope.$new() });
    }));

    it("inherits from BaseCtrl", inject(function ($controller, $rootScope) {
        expect(BaseCtrl).toHaveBeenCalled();
    }));

    it("passes frobnicate() function to BaseCtrl that returns 123", function () {
        var args = BaseCtrl.calls.argsFor(0);
        var frobnicate = args[1];

        expect(frobnicate()).toEqual(123);
    });
});
Michael Kropat
  • 14,557
  • 12
  • 70
  • 91