AngularJS单元测试:将数据从$ q.resolve()附加到object

时间:2016-09-07 11:35:18

标签: angularjs unit-testing jasmine

我正在测试使用其他服务进行API调用的服务,让我们将其称为数据服务。数据服务在其他地方进行了测试,所以我用一个包含空函数的简单实现来抽象它。我通过延迟对象和Jasmine的spyOn语法返回数据。

我用这种方法找到的麻烦是当数据被返回时,它不会立即在调用对象上可用,就像我使用$ httpBackend一样。意识到我可以使用$ httpBackend,但我想知道我是否错过了这种方法(简单或其他方面)。

代码I的示例部分尝试测试:

storeTheData = dataService.getSomeData();
storeTheData.$promise.then(function(data) {

    /*this would work*/
    console.log(data);

    /*but this would not, when testing using $q*/
    _.forEach(storeTheData, function(storedData) {
        /*do something with each object returned*/
    });
});

作为旁注,我不认为这种情况有助于... $ promise.then在另一条线上,但理想情况下我不会改变代码(我提供测试覆盖范围以前写的东西...)

测试示例:

beforeEach(
    ...
    dataService = {
        getSomeData: function () { }
    };
    getSomeDataDeferred = $q.defer();
    spyOn(dataService, "getSomeData").and.returnValue({$promise: getSomeDataDeferred.promise});
    ...
);

it(...
    getSomeDataDeferred.resolve([{obj: "obj1"}, {obj: "obj2"}]);
    $scope.$apply();
    ...
);

通过上述测试,console.log(数据)将是可测试的,因为可以通过传递到.then()来访问数据。但是数据不能立即从storeTheData获得,因此storeTheData [0] .obj将是未定义的。在调试时,如果我通过storeTheData查看附加到storeTheData的promise,我可以看到数据。$$ state.value

就像我说的,我知道我可以使用$ httpBackend,但有没有办法用$ q 来做这个而不用更改测试中的代码?

1 个答案:

答案 0 :(得分:0)

我还没有找到使用$ q.resolve执行此操作的方法,但我确实有一个解决方案,它不涉及使用数据服务或更改测试中的代码。这很好,因为我想避免的主要事情是测试数据服务作为副作用并更改代码。

我的解决方案是通过$ injector ...

创建一个$ resource对象
$resource = $inject.get("$resource");

...然后在我的数据服务的基本实现中返回。这意味着我可以使用$ httpBackend来响应对不依赖于数据服务定义保持一致的终点的请求。

dataService = {
    getSomeData: function () {
        /* new code starts here */
        var resource = $resource(null, null, {
            get: {
                method: "GET",
                isArray: true,
                url: "/getSomeData"
            }
        });

        return resource.get();
       /* new code ends here */
    }
};
...
$httpBackend.when("GET", "/getSomeData").respond(...;