当使用$ resource对控制器进行单元测试时,AngularJS“没有待清除请求”

时间:2014-04-18 17:17:02

标签: angularjs unit-testing jasmine

我正在为控制器编写单元测试。该控制器注入了$ resource服务:

function controller($scope, Service) {
    Service.get(function(result){
        // do stuff with the result, not relevant here
    }
}

服务的定义如下:

angular.module('so').factory('Service', ['$resource', service]);
function service($resource) {
    return $resource('/url', null, {
        get: { method: 'POST', params: {}, isArray: false}
    });
}

我的Jasmine单元测试如下:

describe("Controller", function(){
    var $httpBackend;

    beforeEach(function() {
        module('so');

        inject(function( _$httpBackend_) {
            $httpBackend = _$httpBackend_;
        });
    });
    it('should have done stuff irrelevant to the question', function() {
        var $injector = angular.injector('so'),
            $scope = $injector.get('$rootScope'),

        $httpBackend
            .whenPOST('/url')
            .respond ([]);

        // controller needs to be defined here and not in the beforeEach as there
        // are more parameters passed to it, depending on the test
        var controller = $injector.get('$controller')('controller', { "$scope": $scope });

        $httpBackend.flush();

        // then here the actual test resolution, also irrelevant
    });
});

运行测试时出错:

Error: No pending request to flush ! in file:///path/to/angular-mock.js (line 1453)

我在Service.get()的回调中添加了一个console.log(),实际上,它没有被调用(回调之外的所有内容当然都被调用)。如果在单元测试中控制器创建后没有分阶段,也尝试添加范围摘要,正如我在另一个问题中看到的那样,没有运气。

我知道我可以通过其他方式嘲笑它,但使用$ httpBackend似乎是测试的完美解决方案:模拟网络服务器和收到的数据。

我使用AngularJS 1.2.16(无法升级到1.3。*,需要IE 8兼容性)。我首先使用1.2.13并更新以检查它是否能解决问题,没有任何运气。

1 个答案:

答案 0 :(得分:0)

这是一个通过改变测试来解决的注入问题

it('should have done stuff irrelevant to the question', function() {
    var $injector = angular.injector('so'),
        $scope = $injector.get('$rootScope'),

    $httpBackend
        .whenPOST('/url')
        .respond ([]);

    // controller needs to be defined here and not in the beforeEach as there
    // are more parameters passed to it, depending on the test
    var controller = $injector.get('$controller')('controller', { "$scope": $scope });

    $httpBackend.flush();

    // then here the actual test resolution, also irrelevant
});

致:

it('should have done stuff irrelevant to the question', inject(function(Service) {
    // edited lines because they did not change

    var controller = $injector.get('$controller')('controller', { "$scope": $scope, "Service": Service });

    // edited lines because they did not change
}));

所以基本上,在测试函数中添加inject()并“手动”将服务传递给控制器​​。

我发现了这个问题,这很好,但我真的不明白为什么它不起作用。此外,我在找到解决方案后立即尝试了这个:

it('should have done stuff irrelevant to the question', inject(function() {
    // edited lines because they did not change
    var Service = $injector.get('Service'),

    var controller = $injector.get('$controller')('controller', { "$scope": $scope, "Service": Service });

    // edited lines because they did not change
}));

但是再次失败,同样的“无待处理请求”错误。我猜这是某种竞赛问题,我的服务无法在之后创建时获得正确的$ httpBackend注入,但我真的不明白为什么会发生这种情况。如果有人能开导我......我将不胜感激。