我正在测试使用其他服务进行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 来做这个而不用更改测试中的代码?
答案 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(...;