3

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()没有解决承诺并将返回值重新附加为模型值。我不能做一个简单的平等断言。

我的解决方法是使用承诺捕获模拟:

var result = {
    capture : function(v) { result.value = v; },
    value   : null,
};

然后试试这个:

scope.items.then(result.capture);
expect(result.value).toEqualData(...);

这确实有效(但感觉有点不对)。作为旁注(对于布朗尼点,这不是实际问题),交换result.captureJsonRpc.respond()会导致测试失败(result.value为空)。

以下是问题:测试设置为范围模型的 Promise 的正确方法是什么?这个 result.capture 我做的事情还好吗,还是有更好的方法来解决它?另外,我真的很想知道为什么用响应刷新来反转承诺附件会导致响应无法解析和捕获......?

4

1 回答 1

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)....

这允许您单独测试控制器。

于 2013-02-27T15:49:19.620 回答