简体   繁体   English

如何解决AngularJS单元测试中的承诺

[英]How do I resolve a promise in an AngularJS unit test

I am using the basic karma/jasmine setup to test my Angular code. 我正在使用基本的karma / jasmine设置来测试我的Angular代码。 Here is my test: 这是我的测试:

var $controllerConstructor, ctr, mockSuperheroData, scope, deferred, q;

describe('main controller', function() {
   var $controllerConstructor, ctr, mockSuperheroData, scope, deferred, q;


   beforeEach(inject(function($controller, $rootScope, $q) {
     scope = $rootScope.$new();
     $controllerConstructor = $controller;
     q = $q;
     mockSuperheroData = {
       getSuperheroes: function() {
         deferred = q.defer();
         return deferred.promise;
       }
     };
     ctr = $controllerConstructor('MainCtrl', {$scope: scope, $location: {}, superheroService: mockSuperheroData, keys: {}});
   }));

   it('should set the result of getResource to scope.heroes', function() {
     scope.getHeroes();
     expect(scope.heroes).toBe(100);
   });
}

scope.getHeroes() calls the mockSuperheroData.getSuperheroes() which is returning a promise. scope.getHeroes()调用返回promise的mockSuperheroData.getSuperheroes() How do I force the promise to return what I want in the unit test? 如何强制承诺在单元测试中返回我想要的内容? Where can I hook into the promise to mock out its return? 我在哪里可以接受嘲笑其回报的承诺?

How do I force the promise to return what I want in the unit test? 如何强制承诺在单元测试中返回我想要的内容?

Basically you will need to call resolve on the Deferred : 基本上你需要在Deferred上调用resolve

deferred.resolve(100);

You can either put that directly before the return deferred.promise or in an asynchronous setTimeout . 您可以直接在return deferred.promise之前或在异步setTimeout放置它。

var $controllerConstructor, ctr, mockSuperheroData, scope, deferred, q;

describe('main controller', function() {
  var $controllerConstructor, ctr, mockSuperheroData, scope, deferred, q, rootScope;


  beforeEach(inject(function($controller, $rootScope, $q) {
    scope = $rootScope.$new();
    $controllerConstructor = $controller;
    q = $q;
    rootScope = $rootScope;
    mockSuperheroData = {
      getSuperheroes: function() {
        deferred = q.defer();
        return deferred.promise;
      }
    };
    ctr = $controllerConstructor('MainCtrl', {$scope: scope, $location: {}, superheroService: mockSuperheroData, keys: {}});
  }));

  it('should set the result of getResource to scope.heroes', function() {
    scope.getHeroes();

    deferred.resolve(100);
    rootScope.$apply();

    expect(scope.heroes).toBe(100);
  });
});

It should be mentioned that because $q is integrated with $rootScope, not only do you need to resolve the deferred object, but you also need to propagate the changes by calling $rootScope.$apply. 应该提到的是,因为$ q与$ rootScope集成,所以不仅需要解析延迟对象,还需要通过调用$ rootScope来传播更改。$ apply。

I wrote a blog on mocking angular promises at projectpoppycock 我在projectpoppycock写了一篇关于嘲笑角度承诺的博客

and I wrote a working example, with tests, at plunkr 我在plunkr写了一个带有测试的工作示例

I really like the way you're injecting the mock service as a dependency of the controller by using the $controller service, I may need to revise my way of doing this. 我真的很喜欢你通过使用$ controller服务将模拟服务作为控制器的依赖注入的方式,我可能需要修改我这样做的方式。 Your way is better :) Thanks! 你的方式更好:)谢谢!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM