AngularJS Karma Test Spec Promise未解析且.then()未被调用

时间:2015-03-28 13:44:33

标签: javascript angularjs asynchronous karma-runner angular-promise

我对AngularJS Karma Unit测试服务有疑问。

我的服务方式如下:

service.getIntersectingElements = function (element, elements) {
    var deferred = $q.defer();
    var tolerance = 20;
    var intersectingElements = [];
    $timeout(function () {
        for (var i = 0; i < elements.length; i++) {
            if (element.$$hashKey != elements[i].$$hashKey)
                if (service.checkIntersection(element.Location, elements[i].Location, tolerance))
                    intersectingElements.push(elements[i]);
        }
        if (intersectingElements.length > 0)
            deferred.resolve(intersectingElements);
        else
            deferred.reject();
    });

    return deferred.promise;
};

如果控制器调用它,它可以正常工作。但我想测试该方法,该方法返回稍后解决的promise。我希望得到解决的值并在单元测试中进行比较。

所以我写了下面的业力测试:

it('should get the intersecting elements', function () {
    var element = {Id: 1, Name: 'Water', Location: {x: 200, y: 200}};
    var elements = [{Id: 2, Name: 'Fire', Location: {x: 200, y: 200}}];

    service.getIntersectingElements(element, elements).then(function (result) {
        expect(result).toEqual([{Id: 2, Name: 'Fire', Location: {x: 200, y: 200}}]);
    });
});

我将服务方法与控制器中的方法完全相同。但是测试结束时就完成了。但如果我改变了行

expect(result).toEqual([{Id: 2, Name: 'Fire', Location: {x: 200, y: 200}}]);

expect(result).toEqual("Test");

测试也是如此,并没有失败。但在那种情况下,我希望测试失败。

我已经尝试在服务方法调用之后注入$rootScope并调用$rootScope.$digest();。这应该解决以前的承诺,但事实上,如果我放置摘要,它不会产生任何影响......

所以我的问题是,如何测试服务方法返回的承诺,并比较已解决的值,并在karma单元测试中传递给promise的then()。

编辑: 我在服务方法调用之后尝试了$timeout.flush();$rootScope.$digest();

如果有帮助,我会注入这样的服务:

var service;
var $timeout;
var $rootScope;

beforeEach(module('app'));
beforeEach(module('app.services'));

beforeEach(angular.mock.inject(function (intersectService, _$timeout_, _$rootScope_) {
    service = intersectService;
    $timeout = _$timeout_;
    $rootScope = _$rootScope_;
}));

2 个答案:

答案 0 :(得分:1)

好的,我自己修好了......

首先......我需要刷新超时(我之前尝试过),我需要做一个范围应用

it('should get the intersecting elements', function () {
    var element = {Id: 1, Name: 'Water', Location: {x: 200, y: 200}, $$hashKey: "1"};
    var elements = [
        {Id: 1, Name: 'Water', Location: {x: 200, y: 200}, $$hashKey: "1"},
        {Id: 2, Name: 'Fire', Location: {x: 200, y: 200}, $$hashKey: "2"}
    ];

    var promise = service.getIntersectingElements(element, elements);

    var result;
    promise.then(function (res) {
        result = res;
    },
    function (error) {
        result = "error";
    });

    $rootScope.$apply();
    $timeout.flush();

    expect(result).toEqual([{Id: 2, Name: 'Fire', Location: {x: 250, y: 200}, $$hashKey: "2"}]);
});

现在整个事情就像上面这样。

但第二......那不是真正的错误。我在我的服务方法中使用了$$hashKey属性(参见上面的问题),这显然没有设置,因为我没有在我的测试数据中设置它。通常,如果变量位于$$hashKey,则$scope存在。所以我不记得设置它。

所以答案是设置$$hashKey,如上面的代码所示。

答案 1 :(得分:-1)

如果使用angular.equals,则不需要使用$ hashKey,因为它会忽略$ *属性(和函数)。

TreeField

我添加此作为答案,因为我没有足够的代表发表评论。