#angular #unit-testing #jasmine #karma-runner
#angular #модульное тестирование #jasmine #карма-раннер
Вопрос:
В Angular 7.x у меня есть глобальная обработка ошибок, которая внедряет его сервисы с помощью инжектора. Итак, каждая функция имеет ссылку на инжектор, вот так:
import { ErrorHandler, Injectable, Injector, NgZone } from '@angular/core';
import { Router } from '@angular/router';
import { LoggingService } from '../logging/logging.service';
import { EnvironmentService } from '../services/environment.service';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
constructor(private readonly injector: Injector, private readonly zone: NgZone) {}
handleError(error: any): void {
// Handle Client Error (Angular Error, ReferenceError...)
this.processError(error);
throw error;
}
processError(error: any): void {
const environmentService = this.injector.get(EnvironmentService);
const environment = environmentService.getEnvironment();
if (!environment.production) {
console.error(error);
} else {
// Log the expection to the logger
this.logException(error);
this.zone.run(() => {
this.navigateToErrorPage(error);
});
}
}
private logException(error: any): void {
const loggingService = this.injector.get(LoggingService);
loggingService.logException(error);
}
private navigateToErrorPage(error: any): void {
const router = this.injector.get(Router);
router.navigate(['/500'], { queryParams: { error } });
}
}
Как вы можете видеть, в processError
функцию я внедряю службу окружения. Единственная цель этого сервиса — иметь возможность имитировать среду в моих специальных тестах. Я делаю это в другом тестировании сервиса, но я использую это с внедрением зависимостей, а не с this.injector.get(...)
функцией.
Кто-нибудь знает, как я издеваюсь над этим?
it('should log the error if the environment is in production', () => {
// Arrange
const environmentSpy = jasmine.createSpyObj('EnvironmentService', 'getEnvironment'); ??? How do I mock this ???
const error: Error = new Error('New Error');
spyOn<any>(errorHandler, 'logException');
// Act
errorHandler.processError(error);
// Assert
expect(errorHandler['logException']).toHaveBeenCalledWith(error);
});
Ответ №1:
Вы можете шпионить за инжектором и возвращать поддельный класс вместо EnvironmentService, у которого есть настроенный getEnvironment()
метод:
spyOn(TestBed.get(Injector), 'get').and.callFake((token) => {
if (token === EnvironmentService) {
// Return a mocked EnvironmentService class
return {
getEnvironment: () => { return { production: true }; }
};
} else {
// Otherwise, return whatever was originally defined in the TestBed
return TestBed.get(token);
}
});
В качестве альтернативы, вы могли бы использовать настоящий инжектор и вместо этого следить за EnvironmentService:
spyOn(TestBed.get(EnvironmentService), 'getEnvironment').and
.returnValue({ production: true });
Комментарии:
1. Я использовал последний вариант, который, казалось, сработал! Спасибо!