Why isn't $injector finding $state in my unit

2019-09-08 05:30发布

问题:

The following is my module and unit test set-up. When I try to set $state, $injector.get("$state") throws the always fun Unknown provider: $stateProvider <- $state error and I don't understand why.

angular.module("my-module", [
        //Third Party
        "ui.bootstrap",
        "ui.router",
        "toaster",
        "angular-loading-bar",
        "ngAnimate",
        "ngSanitize",
        "ApplicationInsightsModule",
        "pascalprecht.translate"
]);

describe("something descriptive and helpful", (): void => {
    // a bunch of other service variables....
    var $state: any;

    // I've tried with and without this line
    beforeEach(() => angular.module("ui.router")); 

    beforeEach(() => {

        angular.module("my-module");

        inject(($injector: ng.auto.IInjectorService): void => {
            // a bunch of other service variable assignments
            $state = $injector.get("$state");
        });
});

回答1:

You need to call

angular.mock.module("my-module")

to load the module.



回答2:

The point of mocking $stateProvider and $state is to stub third-party services and test only your own code in isolation, thus reducing the number of moving parts.

It basically is

beforeEach(module("my-module", ($provide) => {
  $provide.factory('$state', ($q) => ({
    go: jasmine.createSpy().andCallFake(() => $q.resolve());
  }));
})); 

it('...', inject(($state, ...) => {
  ...
  expect($state.go).toHaveBeenCalledWith('stateName');
});

At this point ui.router module isn't supposed to be loaded in tested modules because it will require additional stubbing.

See also this answer for the explanation of how $stateProvider route configuration can be tested.