单元测试中的冻结承诺

时间:2016-07-30 14:36:02

标签: javascript angularjs jasmine ngmock

在尝试测试返回普通$ q承诺的服务时,我遇到了一个奇怪的事情。我在任何测试中尝试的承诺实际上都没有得到解决/拒绝(更具体地说,来自then的处理程序没有被调用,promise中的代码运行得很好)。我甚至尝试在根作用域上强制摘要,正如SO提出的其他一些答案所表明的那样,没有任何运气。

这是一个小型的自包含示例:

describe('promise', function(){
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 500;
  let q;

  beforeEach(inject(function($q){
    q = $q;
  }));

  it('finishes', function(done){
    expect(q).toBeDefined();
    const promise = q.resolve();
    console.log(promise);
    promise.then(
      () => done(),
      () => done.fail()
    );
  });
});

我必须做些什么才能使承诺按预期工作?

2 个答案:

答案 0 :(得分:2)

我希望这个例子可以帮助你使用$ rootScope。$ digest()(我知道你已经尝试过强制摘要)。只需忽略类型声明(使用typescript编写)

    var service: IService;
    var $rootScope: ng.IRootScopeService;
    var $q: ng.IQService;

    beforeEach(() => {
        angular.mock.module("app");
        angular.mock.inject((
            _$rootScope_: ng.IRootScopeService,
            _$q_: ng.IQService
        ) => {
            // Assign dependecies
            $q = _$q_;
            $rootScope = _$rootScope_;
        });

        // Initialize service
        service = new Service($q);
    });


    it("should call errorCallback", () => {
        let callback = {
            errorCallback: function (response: any) { /*empty function */ }
        };

        spyOn(callback, "errorCallback");

        service.connect(null)
            .catch(callback.errorCallback);

        // Trigger a digest on rootScope (needed for $q implementation) 
        $rootScope.$digest();

        expect(callback.errorCallback).toHaveBeenCalled();
    });

答案 1 :(得分:1)

你需要使用$ scope。$ apply()(或$ rootScope。$ digest())并在调用之前定义then()。我修改了你的例子:

describe('promise', function(){
  jasmine.DEFAULT_TIMEOUT_INTERVAL = 500;
  let q;
  let scope;

  beforeEach(inject(function($q, $rootScope){
    q = $q;
    scope = $rootScope.$new();
  }));

  it('finishes', function(done){
    expect(q).toBeDefined();
    const promise = q.resolve();
    promise.then(
      () => done(),
      () => done.fail()
    );
    scope.$apply();
  });
});