使用httpBackend进行AngularJS Jasmine单元测试 - rootScope变量未定义

时间:2015-08-29 15:19:08

标签: angularjs unit-testing angularjs-scope jasmine

我有以下控制器

app.controller('NavController', ['$rootScope', '$scope', 'api', function($rootScope, $scope, $location, auth, api) {
    $scope.load = function() {
        return api.get('/location').success(function(data) {
            $rootScope.locations = data;
        }).error(function(data) {
            console.log('load error');
        });
    };
}]);

这是我为它编写的单元测试

describe('Navigation Controller Test', function() {

    beforeEach(module('app'));

    var controller, scope, rootScope, httpBackend;

    beforeEach(inject(function(_$controller_, _$rootScope_, $httpBackend) {
        var $controller = _$controller_;
        rootScope = _$rootScope_;
        scope = rootScope.$new();
        httpBackend = $httpBackend;
        controller = $controller('NavController', {
            $rootScope: rootScope,
            $scope: scope,
        });

        apiRequestHandler = httpBackend.when('GET', '/api/v2/location')
            .respond({userId: 'userX'});

    }));

    afterEach(function() {
        httpBackend.verifyNoOutstandingExpectation();
        httpBackend.verifyNoOutstandingRequest();
    });

    describe('load()', function() {
        it('should have locations when successful', function() {
            httpBackend.expectGET('/api/v2/location');
            scope.load();
            expect(rootScope.locations).toEqual("{userId: 'userX'}");
            httpBackend.flush();
        });
    });
});

我遇到的当前问题是即使在调用rootScope.locations函数后scope.load()未定义。我不太清楚为什么会这样,但我似乎找到的最近的帖子是this我认为可能与我的问题有关,但我不太确定。

当get请求成功并且输出正确时,我在控制器中执行了console.log($rootScope.locations)但是我很难知道如何让它在此测试中显示相同。

1 个答案:

答案 0 :(得分:1)

你不应该在控制器中弄乱rootScope。您的控制器应该只使用$ scope并且为了让茉莉花测试工作,您应该具有beforeEach,如下所示:

var controller, scope, httpBackend;

beforeEach(inject(function(_$controller_, _$rootScope_, $httpBackend) {
    var $controller = _$controller_;
    scope = rootScope.$new();
    httpBackend = $httpBackend;
    controller = $controller('NavController', {
        $scope: scope,
        //authentication dependency and so on
    });

    ...

}));

和你的控制者:

 app.controller('NavController', function($scope, api) {
     $scope.load = function() {
         return api.get('/location').success(function(data) {
             $scope.locations = data;
         }).error(function(data) {
         console.log('load error');
    });
};
});

编辑: 测试流程也应该是:

it('should have locations when successful', function() { 
  scope.load(); 
  httpBackend.expectGET('/api/v2/location'); 
  httpBackend.flush(); 
  expect(rootScope.locations).toEqual("{userId: 'userX'}"); 
}); 

首先需要调用你的函数,而不是期望http后端,下一次刷新,然后再进行验证。另外,httpBackend只能在控制器中使用$ http,而不是第三方ajax调用提供者。