3

У меня есть простой завод

angular.module('myApp.dice',[]).factory('Dice', ['$interval', function($interval){ 
    return { 
     rollDice: function(){ 
     return $interval(function(c){ 
       count++; 
      }, 100, 18, false, 0); 
     } 
    }; 
}]); 

В моем тестовом случае у меня есть

describe('rolling dice', function(){ 
     var promise, promiseCalled = false, notify = false; 
     beforeEach(inject(function(){ 
     promise = Dice.rollDice(); 
     promise.then(function(){ 
      promiseCalled = true; 
     }); 

     })); 

     it('should invoke a promise', inject(function(){ 
     expect(promise).toBeDefined(); 
     })); 

     it('should set promiseCalled', inject(function($rootScope, $interval){ 


     expect(promiseCalled).toEqual(true); 
     })); 
    }); 

Как вызвать интервал или разрешить обещание? чтобы тест был правдой?

ответ

7

См plunker

Вы должны использовать '$interval.flush' из angularjs-издевается, а затем проверить результат. Я взял на себя смелость назначить count объекту кости, потому что он не определен в вашем примере кода.

Есть ли причина, по которой $interval называется invokeApply = false? потому что тогда вам нужно вручную позвонить $apply.

Тестовый пример будет:

describe('rolling dice', function(){ 
    var $interval, $rootScope, dice; 

    beforeEach(module('plunker')); 

    beforeEach(inject(function(_$interval_, _$rootScope_, _Dice_){ 
     $interval = _$interval_; 
     $rootScope = _$rootScope_; 
     dice = _Dice_; 
    })); 

    it('should increment count', inject(function(){ 
     dice.rollDice(); 
     // Move forward by 100 milliseconds 
     $interval.flush(100); 
     // Need to call apply because $interval was called with invokeApply = false 
     $rootScope.$apply(); 
     expect(dice.count).toBe(1); 
    })); 
    }); 

с заводом:

app.factory('Dice', ['$interval', function($interval){ 
    var self= { 
     count: 0, 
     rollDice: function(){ 
     return $interval(function() { 
       self.count++; 
      }, 100, 18, false, 0); 
     } 
    }; 
    return self; 
}]); 

EDIT: Я предпочитаю тестирование результата вызова функции, но, возможно, у вас есть случай использования для тестирования, что функция обещания называется так, что это может быть то, что вы ищете. Из угловых документов на $interval говорится, что он возвращает

Обещание, которое будет уведомлено на каждой итерации.

Ключевое слово являющееся уведомительное. И от promise API аргументы для then являются

then(successCallback, errorCallback, notifyCallback) 

т.е. третий обратный вызов функции notifyCallback вызывается для каждой итерации $interval. Так что тест будет выглядеть примерно так:

it('should set promiseCalled', function(){ 
    var promiseCalled = false; 
    dice.rollDice().then(null, null, function() { 
    promiseCalled = true; 
    }); 
    $interval.flush(100); 
    $rootScope.$apply(); 
    expect(promiseCalled).toBe(true); 
}); 

Если вы хотите проверить на разрешаемое обещание, то это будет выглядеть примерно так:

it('should resolve promise', function(){ 
    var promiseCalled = false; 
    var resolvedData = null; 
    $q.when('Some Data').then(function(data) { 
    promiseCalled = true; 
    resolvedData = data; 
    }); 
    $rootScope.$apply(); 
    expect(promiseCalled).toBe(true); 
    expect(resolvedData).toBe('Some Data'); 
}); 

Я обновил plunker с этим испытанием случаев.

+1

Aaaahhhh .... спасибо. В предыдущем коде у меня был '$ interval.flush', но' $ rootScope. $ Apply' - это что-то новое .... – Kendall

+0

Я просто понимаю, что этот вопрос и решает проблему, не отвечает на соответствующий вопрос .... Как сделать Я тестирую ответ * return callback * от '$ interva()' – Kendall

+1

@ Kendall Обновленный ответ для ответа на ваш последний комментарий – user2718281

Смежные вопросы