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

AngularJS Jasmine unit test with httpBackend - rootScope variable is undefined

我有以下控制器

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() 函数后仍未定义。我不太确定为什么会这样,但我似乎找到的最接近 post 的是 this,我认为它可能与我的问题有关,但我不太确定。

当 get 请求成功时,我在控制器中做了一个 console.log($rootScope.locations),它有正确的输出,但是我不知道如何让它在这个测试中看起来相同。

你不应该乱用控制器中的 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 后端、下一次刷新和仅在之后进行验证有期望。此外,仅当您在控制器中使用 $http 时才能使用 httpBackend,而不是其他第三方 ajax 调用提供程序。