【问题标题】:AngularJS Jasmine unit test with httpBackend - rootScope variable is undefinedAngularJS Jasmine 单元测试与 httpBackend - rootScope 变量未定义
【发布时间】:2015-08-29 15:19:07
【问题描述】:

我有以下控制器

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();
        });
    });
});

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

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

【问题讨论】:

    标签: angularjs unit-testing angularjs-scope jasmine


    【解决方案1】:

    您不应该在控制器中使用 rootScope。你的控制器应该只使用 $scope 并且为了让 jasmine 测试正常工作,你应该有 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 而不是其他第三方 ajax 调用提供程序时,才能使用 httpBackend。

    【讨论】:

    • 感谢您的回复。我已经对其进行了修改,以便控制器使用范围,但是我似乎遇到了 scope.locations 仍然未定义的相同错误。
    • 你能确定你的数据不为空吗?您是否也知道茉莉花测试失败或您调试控制器并且它是空的这一事实?
    • 我发现您的测试流程中存在问题。应该是:it('成功时应该有位置', function() { scope.load(); httpBackend.expectGET('/api/v2/location'); httpBackend.flush(); expect(rootScope.locations) .toEqual("{userId: 'userX'}"); });您需要首先调用您的函数,而不是期望 http 后端、下一次刷新,然后才进行验证。此外,只有在控制器中使用 http,而不是其他第三方 ajax 调用提供程序时,才能使用 httpBacken。
    • 我已验证数据不为空。我检查了 Jasmine 测试并调试了控制器。当我从控制器执行console.log($scope.locations) 时,它似乎正在工作。
    • 啊,解决了!太感谢了。如果您不介意,请您解释一下为什么会通过测试?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 2017-08-19
    • 1970-01-01
    • 2019-06-19
    相关资源
    最近更新 更多