Angularjs中基于单元测试承诺的代码 [英] Unit-test promise-based code in Angularjs

查看:157
本文介绍了Angularjs中基于单元测试承诺的代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难在Angularjs中测试基于promise的代码。

I'm having hard times trying to test promise-based code in Angularjs.

我的控制器中有以下代码:

I have the following code in my controller:

    $scope.markAsDone = function(taskId) {
        tasksService.removeAndGetNext(taskId).then(function(nextTask) {
            goTo(nextTask);
        })
    };

    function goTo(nextTask) {
        $location.path(...);
    }

我想对以下情况进行单元测试:

I'd like to unit-test the following cases:


  • 当调用 markAsDone 时,它应该调用 tasksService.removeAndGetNext

  • tasksService.removeAndGetNext 完成后,它应该更改位置(调用 goTo

  • when markAsDone is called it should call tasksService.removeAndGetNext
  • when tasksService.removeAndGetNext is done it should change location (invoke goTo)

在我看来,没有简单的方法可以单独测试这两种情况。

It seems to me that there is no easy way to test those two cases separately.

我测试第一个的是:

var noopPromise= {then: function() {}}
spyOn(tasksService, 'removeAndGetNext').andReturn(noopPromise);

现在要测试第二种情况我需要创建另一个假承诺解决。这一切都非常繁琐,并且它是很多样板代码。

Now to test the second case I need to create another fake promise that would be always resolved. It's all quite tedious and it's a lot of boilerplate code.

还有其他方法来测试这些东西吗?或者我的设计有异味吗?

Is there any other way to test such things? Or does my design smell?

推荐答案

您仍然需要模拟服务并返回承诺,但您应该使用真正的承诺相反,所以你不需要实现它的功能。使用 beforeEach 创建已履行的承诺,并在需要时模拟服务以便始终得到解决。

You will still need to mock the services and return a promise, but you should use real promises instead, so you don't need to implement its functionality. Use beforeEach to create the already fulfilled promise and mock the service if you need it to ALWAYS be resolved.

var $rootScope;

beforeEach(inject(function(_$rootScope_, $q) {
  $rootScope = _$rootScope_;

  var deferred = $q.defer();
  deferred.resolve('somevalue'); //  always resolved, you can do it from your spec

  // jasmine 2.0
  spyOn(tasksService, 'removeAndGetNext').and.returnValue(deferred.promise); 

  // jasmine 1.3
  //spyOn(tasksService, 'removeAndGetNext').andReturn(deferred.promise); 

}));

如果您更愿意在每个中解决它阻止具有不同的值,然后您只需将延迟公开给一个局部变量并在规范中解决它。

If you'd rather prefer to resolve it in each it block with a different value, then you just expose the deferred to a local variable and resolve it in the spec.

当然,你会保留你的测试虽然它们是,但这里有一些非常简单的规范,告诉你它是如何工作的。

Of course, you would keep your tests as they are, but here is some really simple spec to show you how it would work.

it ('should test receive the fulfilled promise', function() {
  var result;

  tasksService.removeAndGetNext().then(function(returnFromPromise) {
    result = returnFromPromise;
  });

  $rootScope.$apply(); // promises are resolved/dispatched only on next $digest cycle
  expect(result).toBe('somevalue');
});

这篇关于Angularjs中基于单元测试承诺的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆