【问题标题】:$httpBackend.flush() getting into inifinite loop$httpBackend.flush() 进入无限循环
【发布时间】:2014-05-09 16:01:14
【问题描述】:

我想彻底,所以请耐心等待,这里会有很多。我们有一个远程日志服务功能,可以在我们需要时向我们发送一些客户端信息。像这样的:

callHome: function(message){
    var deferred, promise;
    try{
        if (someService.getRemoteLoggingEnabled())
        {
            //collect all the info into remoteLog
            promise = $http.post("Logging", remoteLog);
            wipeLog();
        }
        else
        {
            deferred = $q.defer();
            promise = deferred.promise;
            deferred.resolve();
        }
    }
    catch(error)
    {
        try{
            if (!promise)
            {
                deferred = $q.defer();
                promise = deferred.promise;
            }
            deferred.reject(error.message);
        }
        catch(e2){}
    }
    return promise;
}

在实际应用程序中运行时,一切正常。尝试为其编写单元测试时会出现问题。我对何时未启用远程日志记录以及何时出现错误进行了测试。这些看起来像这样:

it ("should resolve the promise with nothing when remote logging is turned off", inject(function($rootScope) {
    remoteLoggingEnabled = false; //this is declared above a beforeEach that mocks getRemoteLoggingEnabled
    var successSpy = jasmine.createSpy("success");
    var failSpy = jasmine.createSpy("fail");
    var promise = loggingService.callHome("Hello World");
    promise.then(successSpy, failSpy);
    $rootScope.$digest();

    expect(successSpy).toHaveBeenCalledWith(undefined);
    expect(failSpy).not.toHaveBeenCalled();
}));
it ("should reject the promise when there is an error with the error message", inject(function($rootScope) {
    remoteLoggingEnabled = true;
    var successSpy = jasmine.createSpy("success");
    var failSpy = jasmine.createSpy("fail");
    //angular.toJson is called while it's gathering client-side info
    spyOn(angular, "toJson").andCallFake(function() {throw new Error("This is an error");}); 
    var promise = loggingService.callHome("Hello World");
    promise.then(successSpy, failSpy);
    $rootScope.$digest();

    expect(successSpy).not.toHaveBeenCalled();
    expect(failSpy).toHaveBeenCalledWith("This is an error");
}));

这些效果很好。接下来我想添加测试,以了解它何时实际发出请求。我做了一个这样的测试:

it ("should resolve the promise with the http info when it makes a successful request", inject(function($rootScope, $httpBackend) {
    remoteLoggingEnabled = true;
    var successSpy = jasmine.createSpy("success");
    var failSpy = jasmine.createSpy("fail");
    $httpBackend.expect("POST", new RegExp("Logging"), function(jsonStr){
        //not concerned about the actual payload
        return true;
    }).respond(200);
    var promise = loggingService.callHome("Hello World");
    promise.then(successSpy, failSpy);
    $httpBackend.flush();
    $rootScope.$digest();

    expect(successSpy).toHaveBeenCalledWith(/*http info*/);
    expect(failSpy).not.toHaveBeenCalled();
}));

但是,这个测试只是挂起。我单步执行了代码,它卡在了$httpBackend.flush()$rootScope.$digest() 调用中,特别是在这个while 循环中:

      while(asyncQueue.length) {
        try {
          asyncTask = asyncQueue.shift();
          asyncTask.scope.$eval(asyncTask.expression);
        } catch (e) {
          clearPhase();
          $exceptionHandler(e);
        }
        lastDirtyWatch = null;
      }

我已经检查了 asyncTask.expression 的循环,但我找不到它正在做的任何模式。

我仍然掌握了 Promise 以及如何使用它们,所以我希望我在这里做的只是一些根本上的错误。任何帮助将不胜感激。

【问题讨论】:

    标签: javascript angularjs unit-testing jasmine promise


    【解决方案1】:

    问题只是在我的测试设置中(未显示为问题的一部分)。只要通过修饰的$exceptionHandler 出现错误,就会调用这个callHome 函数。在callHome 的测试过程中出现错误,因此再次调用它,然后从那里循环。我修复了这个错误,现在一切正常。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多