javascript - $rootScope.digest 没有完成 Jasmine 中的 promise

标签 javascript angularjs jasmine angular-promise

我们目前正在尝试测试我们的 Angular 服务,它使用 promise 将值返回给 Controller 。问题是我们附加到 .then 的函数不会在 Jasmine 中被调用。

我们发现在返回 promise 后将 $rootScope.digest() 添加到函数中允许调用同步 promise,但它仍然不适用于异步 promises。

目前的代码是

    beforeEach(inject(function (Service, $rootScope)
    {
        service = Service;
        root = $rootScope;
    }));

    it('gets all the available products', function (done)
    {
        service.getData().then(function (data)
        {
            expect(data).not.toBeNull();
            expect(data.length).toBeGreaterThan(0);
            done();
        });
        root.$digest();
    });

在这种情况下,promise 被调用得很好,但如果它是异步的,它将不会被调用,因为在调用 root.$digest() 时 promise 还没有准备好“消化”。

有没有什么方法可以判断 promise 何时在解决后才能调用 digest?或者也许可以自动执行此操作?谢谢 ;)

我们必须测试的部分服务(删除了错误处理):

var app = angular.module('service', []);

/**
 * Service for accessing data relating to the updates/downloads
 * */
app.factory('Service', function ($q)
{
     ... init

    function getData()
    {
        var deffered = $q.defer();

        var processors = [displayNameProc];

        downloads.getData(function (err, data)
        {
            chain.process(processors, data, function (err, processedData)
            {
                deffered.resolve(processedData);
            });
        });

        return deffered.promise;
    }
    ...

在出现问题的情况下,当 service.getData 异步时,promise 已解决,但未调用测试代码中附加到该 promise 的函数,因为 root.$digest 已被调用。希望这能提供更多信息

解决方法

var interval;
beforeEach(inject(function ($rootScope)
{
    if(!interval)
    {
        interval = function ()
        {
            $rootScope.$digest();
        };
        window.setInterval(interval, /*timing*/);
    }
}));

我最终使用上面的解决方法重复调用摘要,这样每一层 promise 都有机会运行......它不理想或不漂亮但它适用于测试......

最佳答案

你应该把你的断言移到 then 之外,我相信:

beforeEach(inject(function (Service, $rootScope)
{
    service = Service;
    root = $rootScope;
}));

it('gets all the available products', function (done)
{
    var result;
    service.getData().then(function (data)
    {
        result = data;
        done();
    });

    root.$digest();

    expect(result ).not.toBeNull();
    expect(result .length).toBeGreaterThan(0);
});

更新

fork plunkr在下面的评论中显示如何测试异步调用。

向服务添加了 $timeout:

var app = angular.module('bad-service', []);

app.service('BadService', function ($q, $interval, $timeout)
{
    this.innerPromise = function(){
      var task = $q.defer();
      console.log('Inside inner promise');

      $timeout(function() {
        console.log('Inner promise timer fired');
        task.resolve();
      }, 500);
      // $interval(function(){

      // }, 500, 1);
      return task.promise;
    }
});

我在断言之前刷新 $timeout:

beforeEach(module('test'));


describe('test', function(){
  var service, root, $timeout;

    beforeEach(inject(function (Service, $rootScope, _$timeout_)
    {
      $timeout = _$timeout_;
        console.log('injecting');
        service = Service;
        root = $rootScope;
    }));

    /**
    Test one
    */
    it('Should work', function(done){
      console.log('Before service call');
      service.outerPromise().then(function resolve(){
        console.log('I should be run!');
        expect(true).toBeTruthy();
        done();
      });
      // You will have to use the correct "resolve" here. For example when using:
      // $httpbackend - $httpBackend.flush();
      // $timeout- $timeout.flush();
      $timeout.flush();

      console.log('After service call');
    });
});

关于javascript - $rootScope.digest 没有完成 Jasmine 中的 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32717897/

相关文章:

Javascript null 或空字符串不起作用

javascript - 使用 AMP HTML,是否可以从单击的元素获取 ID 或其他属性,附加它们并为 anchor 标记创建 URL?

angularjs - 使用 ng-controller 时延迟模板加载

angularjs - 当另一个元素等于 Protractor 和 Jasmine 的特定输入时,单击中继器内的一个元素

angular - 如何在 Angular Testing 中检索 ngClass 的值?

javascript - Input.checked 创建需要绑定(bind)到输入的动态元素

javascript - jquery加载附加日期选择器函数

javascript - 在 Controller 中使用 angularJS 从 firebase 对象获取值

javascript - 如何更改输入日期格式?

angular - 在 Angular 中使用 TypeScript 对文件大小进行 Jasmine 单元测试