2016-09-13 4 views
0

У меня есть стандартный HTTP-перехватчик как фабрика:Unit тестирование Угловая HTTP-перехватчик

angular 
    .module('app.services') 
    .factory('HttpInterceptorService', HttpInterceptorService); 

function HttpInterceptorService($injector) { 

    // Callable functions 
    var service = { 
    response: response, 
    responseError: responseError 
    }; 

    return service; 

    // Pass through clean response 
    function response(data) { 
    return data; 
    } 

    // Handle error response 
    function responseError(rejection) { 

    // Handle bypass requests 
    if (angular.isDefined(rejection.config) && rejection.config.bypassInterceptor) { 
     return rejection; 
    } 

    // Get $state via $injector to avoid a circular dependency 
    var state = $injector.get('$state'); 

    switch (rejection.status) { 
     case 404: 
     return state.go('404'); 
     break; 
     default: 
     return state.go('error'); 
    } 
    } 

} 

В ручном тестировании, я могу видеть, что это работает правильно перенаправлять пользователя на соответствующей странице 404 или ошибки, если HTTP вызов возвращает ответ об ошибке. Основной принцип этого задокументирован Угловыми здесь: https://docs.angularjs.org/api/ng/service/ $ HTTP # перехватчиками

Сейчас я пытаюсь написать модульный тест с Karma & жасмином, чтобы проверить, что функция responseError работает правильно. Я проверил this SO answer, чтобы помочь мне. Мой тест выглядит следующим образом:

describe('HttpInterceptorService', function() { 

    // Bindable members 
    var $window, 
     HttpInterceptorService; 

    // Load module 
    beforeEach(module('app.services')); 

    // Set window value 
    beforeEach(function() { 
    $window = { location: { href: null } }; 

    module(function($provide) { 
     $provide.value('$window', $window); 
    }); 
    }); 

    // Bind references to global variables 
    beforeEach(inject(function(_HttpInterceptorService_) { 
    HttpInterceptorService = _HttpInterceptorService_; 
    })); 

    // Check service exists with methods 
    it('Exists with required methods', function() { 
    expect(HttpInterceptorService).toBeDefined(); 
    expect(angular.isFunction(HttpInterceptorService.response)).toBe(true); 
    expect(angular.isFunction(HttpInterceptorService.responseError)).toBe(true); 
    }); 

    // Test 404 HTTP response 
    describe('When HTTP response 404', function() { 
    beforeEach(function() { 
     HttpInterceptorService.responseError({ status: 404 }); 
    }); 

    it('Sets window location', function() { 
     expect($window.location.href).toBe('/404'); 
    }); 
    }); 

}); 

Мой тест проходит Exists with required methods проверку, но не Sets window location со следующей ошибкой:

Error: [$injector:unpr] Unknown provider: $stateProvider <- $state 
+0

Вам нужно будет отредактировать службу, поскольку вы проверяете свойства неопределенного объекта. rejection.config.bypassInterceptor undefined, что означает, что вам нужно добавить angular.isDefined (rejection) && перед оператором if. – Tom

+0

@Tom Спасибо за помощь. Это помогло мне преодолеть эту первоначальную ошибку, но у меня все еще есть ошибка. Я обновил свой вопрос, чтобы показать – Coop

+0

Думаю, вам придется издеваться над сервисом $ window, поставив шпиона на него. – Tom

ответ

1

модуль, кажется, не имеют ui.router модуль загружен, поэтому $state обслуживание не определено. Это прекрасно, потому что настоящий маршрутизатор вводит дополнительные движущиеся части и очень нежелателен в модульных тестах.

Для функциональных испытаний нормально рассматривать устройство как черный ящик, обеспечивать начальные условия и проверять результаты, утверждая, что window.location будет уместным.

Для модульного тестирования нет необходимости рассматривать блок как Blackbox, $state услуга может быть потушил:

var statePromiseMock = {}; 
beforeEach(module('app.services', { 
    $state: { 
    go: jasmine.createSpy().and.returnValue(statePromiseMock) 
    } 
})); 

и испытаны, как:

it('...', inject(function (HttpInterceptorService, $state) { 
    var state404Promise = HttpInterceptorService.responseError({ status: 404 }); 
    expect($state.go).toHaveBeenCalledWith('404'); 
    expect(state404Promise).toBe(statePromiseMock); 
    ... 
})) 

Т.е. это может быть что-то вроде

describe('HttpInterceptorService', function() { 

    // Bindable members 
    var HttpInterceptorService; 

    var statePromiseMock = {}; 
    beforeEach(module('app.services', { 
    $state: { 
     go: jasmine.createSpy().and.returnValue(statePromiseMock) 
    } 
    })); 

    // Bind references to global variables 
    beforeEach(inject(function(_HttpInterceptorService_) { 
    HttpInterceptorService = _HttpInterceptorService_; 
    })); 

    // Check service exists with methods 
    it('Exists with required methods', function() { 
    expect(HttpInterceptorService).toBeDefined(); 
    expect(angular.isFunction(HttpInterceptorService.response)).toBe(true); 
    expect(angular.isFunction(HttpInterceptorService.responseError)).toBe(true); 
    }); 

    it('...', inject(function($state) { 
    var state404Promise = HttpInterceptorService.responseError({ 
     status: 404 
    }); 
    expect($state.go).toHaveBeenCalledWith('404'); 
    expect(state404Promise).toBe(statePromiseMock); 
    })) 

}); 
+0

Это, кажется, не работает для меня. Я получаю сообщение об ошибке «Не могу найти переменную: $ state» для этой строки: 'ожидать ($ state.go) .toHaveBeenCalledWith ('404');' – Coop

+0

Это сервис, который должен быть инъецирован 'inject', as любой другой. – estus

+0

Вы могли бы привести пример того, как будет выглядеть мой тест? Я просто не могу заставить это работать с вашими инструкциями. – Coop

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