AngularJS为您做的许多魔法之一是自动承诺解析,以便您可以编写如下代码:
function SomeCtrl($scope, Resource) {
$scope.items = Resource.query();
}
然而,我通过JSON-RPC和ngResource使用函数的服务似乎不能很好地使用它。我不得不嘲笑后端做出适当的回应,但出于某种原因,我似乎无法弄清楚如何在控制器级别测试响应。
"use strict";
describe('controllers', function() {
describe('LibraryCtrl', function() {
var scope, ctrl;
beforeEach(inject(function($rootScope, $controller) {
JsonRpc.respondWith({ some : data });
scope = $rootScope.$new();
ctrl = $controller(LibraryCtrl, { $scope : scope });
// controller does `$scope.items = RPCService.get()`
}));
it("should create a `items` model with data fetched via JSON-RPC", function() {
// here's where I'm very confused
// JsonRpc does $httpBackend.flush()
JsonRpc.respond();
// now I want to inspect the property on the controller
expect(scope.items).toEqualData( { some : data } );
});
});
});
问题是,scope.items
是一个承诺。该特定属性仍然是一个承诺,因为显然$digest()
不解析承诺并重新附加返回值作为模型值。我不能做一个简单的平等断言。
我的解决方法是使用promise capture mock:
var result = {
capture : function(v) { result.value = v; },
value : null,
};
然后试试这个:
scope.items.then(result.capture);
expect(result.value).toEqualData(...);
这确实有效(但感觉有些不对劲)。作为旁注(对于布朗尼点,这不是实际问题),用result.capture
交换JsonRpc.respond()
链会导致测试失败(result.value
为空)。
以下是问题:测试作为范围模型的承诺的正确方法是什么?这是结果吗。我正在做的事情还好,还是有更好的方法去做?另外,我真的想知道为什么用响应刷新来反转promise附件导致响应无法解决和捕获......?
答案 0 :(得分:2)
好问题。我的第一反应是你的控制器单元测试实际上是在这里测试ngResource。在我的控制器测试中,我模拟了资源:
mockResource = {query: jasmine.createSpy('query').andReturn([{id: 1, name: foo}])
module(function ($provide) {
$provide.value('Resource', mockResource);
...
expect(mockResource.find).toHaveBeenCalled()
expect(scope.items)....
这允许您单独测试控制器。