单元测试中的冻结承诺

Frozen promise in a unit test

我在尝试测试返回普通 $q 承诺的服务时遇到了一件奇怪的事情。我在任何测试中尝试的承诺实际上都不是 resolved/rejected(更具体地说,来自 then 的处理程序未被调用,承诺中的代码运行得很好)。我什至尝试在根范围内强制摘要,正如 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()
    );
  });
});

我需要做什么才能让 promise 按预期工作?

我希望这个示例可以帮助您使用 $rootScope.$digest()(我知道您已经尝试过强制摘要)。忽略类型声明(使用打字稿编写)

    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();
    });

您需要使用$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();
  });
});