AngularJS Karma 测试规范 Promise 未解决且未调用 .then()

AngularJS Karma Test Spec Promise not resolved and .then() not called

我在 AngularJS Karma 单元测试服务时遇到问题。

我有一个服务方法是这样的:

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

控制器调用它就可以正常工作。但我想测试那个方法,returns 稍后解决了一个承诺。我想得到值解析并在单元测试中比较它。

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

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 单元测试中测试 service 方法返回的 promise 并比较已解析并传递给 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_;
}));

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

首先...我需要刷新超时(我之前尝试过)并且我需要应用范围

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 属性 (参见上面的问题),(显然)没有设置,因为我没有在我的测试数据中设置它。如果变量在 $scope 上,通常 $$hashKey 存在。所以没记得设置。

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

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

expect(angular.equals(result, [{Id: 2, Name: 'Fire', Location: {x: 250, y: 200}}])).toBe(true);

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