Error: Timeout - Async callback was not invoked within timeout specified… .DEFAULT_TIMEOUT_INTERVAL

后端 未结 1 461
情书的邮戳
情书的邮戳 2021-02-08 07:06

I have an angular service class : -

angular.module(\'triggerTips\')
       .service(\'userData\', function ($rootScope, $http, $log, $firebase) {

    this._log         


        
1条回答
  •  清歌不尽
    2021-02-08 07:48

    I would suggest that you replace setTimeout with $timeout so as to speed up your spec suite. You will need ngMock to be a part of your spec suite in order to get this working the intended way, but that seems to have already been taken care of looking at your spec. Good stuff.

    Then in order to make the async nature of the spec "go away" you would call:

    $timeout.flush([delay]) where delay is optional.

    • If no delay is passed, all the pending async tasks (inside the angular world) will finish what they're doing.
    • If a delay is passed, all pending tasks within the specified delay will finish. Those outside of the specified delay will remain in a 'pending' state.

    With this, you can remove the done callback and write your tests as such:

    describe('after being initialized', function () {
      var $timeout;
    
      beforeEach(function () {
        // Unable to get this working because the callback is never called
        userData.init();
    
        inject(function ($injector) {
          $timeout = $injector.get('$timeout');
        });
      }));
    
      it('should have a valid config', function () {
        $timeout.flush();
        // callback should've been called now that we flushed().
        expect(Object.keys(userData.getConfig()).length).toEqual(0);
      });
    });
    

    What Promise implementation are you using? I see a call to Promise.all but for the sake of continuing on with my answer I'm going to assume it is equivalent to $q.all. Running $timeout.flush should take care of resolving those values.

    If you want to write expectations on the rejected/resolved values of a promise in Jasmine, I would look into something like jasmine-promise-matchers to make it clean and pretty, but barring that you could do something like this:

    // $q
    function get () {
      var p1 = $timeout(function () { return 'x'; }, 250);
      var p2 = $timeout(function () { return 'y'; }, 2500); 
    
      return $q.all([p1, p2]);
    }
    
    // expectation
    it('is correct', function () {
      var res; 
    
      get().then(function (r) {
        res = r;
      });
    
      $timeout.flush(2500);
    
      expect(res).toEqual(['x', 'y']);
    });
    

    Depending on your setup, you may or may not have to stub out/spy on (depending on your frameworks definition of a spy) the promise in relation to your local config variable, but that's another story altogether I reckon.

    I am not at all familiar with $firebase(something).$asObject.$loaded - as such I may have missed something here, but assuming it works 'just like any other promise' you should be good to go.

    jsfiddle

    0 讨论(0)
提交回复
热议问题