2015-01-27 4 views
5

Ниже я использую следующий код для сброса $broadcast после каждого тестового примера, но, похоже, он $rootScope.$broadcast.reset(); не работает должным образом, так как тестовый рев должен возвращать 1, но она возвращает 6.Сбросить трансляцию() после каждого тестового примера при использовании andCallThrough()

Кажется, что причиной этого является andCallThrough(), так как прежде, чем я использовал его без andCallThrough() функции, но через какое-то реорганизовать он дал мне ошибку, что TypeError: Cannot read property 'defaultPrevented' of undefined, так что я должен был использовать, чтобы предотвратить эту ошибку.

Вопрос в том, как я могу сбросить broadcast при использовании andCallThrough или есть еще один более точный подход?

beforeEach(function() { 
    spyOn($http, 'post'); 
    spyOn($rootScope, '$broadcast').andCallThrough(); 
}); 

afterEach(function() { 
    $http.post.reset(); 
    $rootScope.$broadcast.reset(); 
}); 

it('should make a POST request to API endpoint', function() { 
    $http.post.andCallThrough(); 
    var response = { id: '123', role: 'employee', email: '[email protected]', username: 'someUsername' }; 
    $httpBackend.expectPOST(apiUrl + 'login').respond(response); 
    service.login(); 
    $httpBackend.flush(); 
    $timeout.flush(); 
    expect($rootScope.$broadcast.callCount).toBe(1); 
    expect($rootScope.$broadcast).toHaveBeenCalledWith(AUTH_EVENTS.loginSuccess, response); 
}); 
+1

Если вызов «ожидать» тестирования 'callCount' переносится в первую строку теста, что означает' callCount' равно тогда? Интересно, что что-то еще в тесте вызывает '$ broadcast'. –

ответ

4

После длительного расследования о том, как обстоят дела в этой ситуации, наконец, испытания прошли и раствор тока:

Речь идет не о переустановку трансляции() или reset метод не вызывается после того, как после каждого испытания при использовании andCallThrough(). Проблема заключается в том, что $rootScope.$broadcast.andCallThrough(); запускается другими событиями и возвращается функция .callCount()6, что в основном означает $broadcast. Шпион был вызван 6 раз.В моем случае меня интересует только событие AUTH_EVENTS.loginSuccess и убедитесь, что оно транслировалось только один раз.

expect($rootScope.$broadcast.callCount).toBe(1); 
expect($rootScope.$broadcast).toHaveBeenCalledWith(AUTH_EVENTS.loginSuccess, response); 

Таким образом, рытье метода $rootScope.$broadcast.calls дал мой массив всех вызовов, из которых два выше ожидает должны быть восстановлены. Следовательно, решение:

it('should make a POST request to API endpoint', function() { 
    $http.post.andCallThrough(); 
    var response = { id: '123', role: 'employee', email: '[email protected]', username: 'someUsername' }; 
    $httpBackend.expectPOST(apiUrl + 'login').respond(response); 
    service.login(); 
    $httpBackend.flush(); 
    $timeout.flush(); 

    var loginSuccessTriggerCount = _($rootScope.$broadcast.calls) 
    .chain() 
    .map(function getFirstArgument(call) { 
     return call.args[0]; 
    }) 
    .filter(function onlyLoginSuccess(eventName) { 
     return eventName === AUTH_EVENTS.loginSuccess; 
    }) 
    .value().length; 

    expect(loginSuccessTriggerCount).toBe(1); 
}); 
2

Другой подход. Это псевдо-код, похожий на coffeescript. Спросите в комментариях, если некоторые выражения не ясны. Должен сказать, что это не прямой ответ на ваш вопрос. Просто метод, как делать подобные вещи по-другому.

тесты с более чистого состояния

Пусть ввести переменную, которая будет обрабатывать шпион для вещания. Я использую чистых шпионов, потому что spyOn может работать плохо в некоторых громоздких случаях, когда мы имеем дело с переопределением или смешиванием метода.

rootScope$broadcastSpy = jasmine.createSpy() 

Мы должны поменять реализацию происхождения с заглушкой который будет обрабатывать шпион и их состояние. В обычном определении заглушки говорится, что это сущность, которая не имеет своей собственной логики. Итак, мы делаем это чистым способом и не ставим здесь никакой логики. Только маркер (который представлен шпионом).

beforeEach module ($provide) -> 
    $provide.value '$rootScope', 
    $broadcast: rootScope$broadcastSpy 

    return 

Несомненно, нам нужно поговорить с жасмином, когда нам нужно сбросить шпион.

beforeEach -> 
    rootScope$broadcastSpy.reset() 

Давайте определим тестирования сферы, где мы подготовим все необходимые услуги и поместить их в декларативно в контексте (т.е. this).

instance = (fnAsserts) -> 
    inject (loginService, $httpBackend, $timeout, apiUrl, AUTH_EVENTS) -> 
    fnAsserts.call 
     service: loginService 
     apiUrl: apiUrl 
     AUTH_EVENTS: AUTH_EVENTS 
     '$httpBackend': $httpBackend 
     '$timeout': $timeout 

Давайте напишем тест в режиме Blackbox. Мы просто устанавливаем начальное состояние, а затем начинаем действие, и в конце давайте проверим наш маркер на изменения.

it 'should make a POST request to API endpoint', instance -> 
    # Given 
    response = { id: '123', role: 'employee', email: '[email protected]', username: 'someUsername' } 
    @$httpBackend.expectPOST(@apiUrl + 'login').respond(response) 

    # When 
    @service.login() 

    # Then 
    @$httpBackend.flush() 
    @$timeout.flush() 
    expect(rootScope$broadcastSpy.callCount).toBe(1) 
    expect(rootScope$broadcastSpy).toHaveBeenCalledWith(@AUTH_EVENTS.loginSuccess, response) 

Как вы видите, мы можем экземпляра цепи defitions, добавить больше информации для них и писать каждый тест в более чистом пути, потому что мы видим, состояние, объем, издевается и другие необходимые вещи в одном месте. Мы используем закрытие только для маркера, и оно гарантирует, что побочные эффекты будут минимальными.

+0

Спасибо @Gulin за ваш ответ, так как я не знаком с CoffeeScript, это решение кажется неясным. В частности, функция 'beforeEach module ($ обеспечивать) -> \ n $ обеспечивает.значение '$ rootScope', \ n $ broadcast: rootScope $ broadcastSpy \ n return' Что возвращает' return'? – Max

+0

В кофе каждая последняя строка - это возврат. Но здесь я положил возвращение явно, чтобы ничего не вернуть. Реализация 'module' использует возвращаемое значение, и я избегаю этого поведения, возвращая' undefined' через пустой возврат. –

0

я оказался здесь в первой части вопроса

Сброс вещания()

и это работает для меня:

$rootScope.$broadcast.calls.reset() 
Смежные вопросы