【问题标题】:Unit testing promises attached to an AngularJS Scope附加到 AngularJS 范围的单元测试承诺
【发布时间】:2013-01-29 06:56:27
【问题描述】:

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.capture 链与JsonRpc.respond() 交换会导致测试失败(result.value 为空)。

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

【问题讨论】:

  • 你解决过这个问题吗?我遇到了同样的问题。我目前正在通过做类似 Resource.query().then(function(value) { $scope.items = value }) 的方法来解决它,但这不是很优雅......

标签: javascript angularjs


【解决方案1】:

好问题。我的第一反应似乎是您的控制器单元测试实际上是在这里测试 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)....

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

【讨论】:

  • 啊,有道理。我仍然对自动承诺解决以一种我无法轻易改变用途的方式感到不满意,但我的测试范围超出了只是控制器的功能确实是有道理的。我很感激这个答案,即使我已经不再使用 Angular 了;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-15
  • 2014-03-05
  • 2016-07-25
  • 2014-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多