How do I inject $rootScope into an AngularJS unit

2019-02-04 19:40发布

问题:

Suppose I have a service that depends on a value in $rootScope, as with the following (trivial) service:

angular.module('myServices', [])
.factory('rootValGetterService', function($rootScope) {
    return {
        getVal: function () {
            return $rootScope.specialValue;
        }
    };
});

If I want to unit test this by putting a value in $rootScope, what is the best way to go about it?

回答1:

...
var $rootScope;
beforeEach(inject(function(_$rootScope_) {
  $rootScope = _$rootScope_;
}));
...


回答2:

By using provide(), you can inject a new $rootScope:

describe('in rootValGetter', inject(function ($rootScope) {
    var scope;
    var testRootValGetter;

    beforeEach(function () {

        scope = $rootScope.$new();

        module(function ($provide) {
            $provide.value('$rootScope', scope);
        });

        inject(function ($injector) {
            testRootValGetterService = $injector.get('rootValGetterService');
        });
    });

    it('getVal returns the value from $rootScope', function() {
        var value = 12345;

        scope.specialValue = value;

        expect(testRootValGetterService.getVal()).toBe(value);
    }
}


回答3:

Include angular-mocks.js, then use angular.mock.inject:



回答4:

Just try to give a more detailed answer including the test case:

...

var $rootScope;
beforeEach(inject(function(_$rootScope_) {
  $rootScope = _$rootScope_;
}));

...

  it('getVal returns the value from $rootScope', function() {
        var value = 12345;
        $rootScope.specialValue = value;
        expect(testRootValGetterService.getVal()).toBe(value);
    }


回答5:

Here's what I did:

it('some kind of wacky test', function($rootScope, Translate){
    $rootScope.lang = 'en';
    expect(Translate('overview').toBe('Overview');
}


回答6:

Hope this helps others as this was the solution to a similar problem.

var rootValGetterService;

beforeEach(inject(function($rootScope,$injector) {
    $rootScope.specialValue = "test";
    rootValGetterService= $injector.get('rootValGetterService');
}));

it("Should have a service", function () {
    expect(rootValGetterService).toBeDefined();
});


回答7:

Instead of creating a new scope as you would if you were injecting $scope you can mock the properties you need directly into $rootScope.

Then $rootScope will be injected with those properties available in the code you are testing.

At least this is the way I solved the same problem.

The following code should work in your example.

beforeEach(inject(function($rootScope) {
    $rootScope.specialValue = 'whatever';
}));