Я пишу модульные тестовые примеры в Angular 7, в этом процессе застрял, чтобы создать модуль проверка служебной переменной isLoading.
вот мой html-файл компонента приложения:
<router-outlet></router-outlet>
<div *ngIf = "guestUserService.isLoading | async" class = "loaderdiv">
<mat-spinner class = "loader"></mat-spinner>
</div>
Сервисный файл:
export class GuestUserService {
public isLoading: any = new BehaviorSubject(false);
}
Пример модульного теста:
fdescribe('AppComponent', () => {
let guestUserService: any;
let guestUserServiceSpy: any;
beforeEach(async(() => {
guestUserService = jasmine.createSpyObj('GuestUserService', ['isLoading']);
TestBed.configureTestingModule({
providers: [
{ provide: GuestUserService, useValue: guestUserService }]
}).compileComponents();
}));
it('should render loader if isLoading true', () => {
guestUserServiceSpy = guestUserService.isLoading.and.returnValue(true);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(guestUserService).toBeDefined();
expect(guestUserServiceSpy).toBeDefined();
expect(guestUserService.isLoading).toBeTruthy();
expect(fixture.debugElement.query(By.css('.loader'))).toBeDefined();
expect(compiled.querySelector('mat-spinner')).toBeTruthy();
});
Получение ошибки:
Error: InvalidPipeArgument: 'function () { return fn.apply(this, arguments); }' for pipe 'AsyncPipe'
Есть ли правильный способ создать модульный тестовый пример для такого типа сценариев.





Есть несколько проблем.
Во-первых, вы стреляете себе в ногу, используя тип any. Делая это, компилятор позволяет вам делать вещи, которые не имеют смысла. И вы также затрудняете чтение кода для себя. Свойство isLoading должно быть Observable<boolean>, так как это то, что ожидает шаблон. Так что используйте этот правильный тип вместо any.
Во-вторых, эта строка:
jasmine.createSpyObj('GuestUserService', ['isLoading'])
создает объект с функция с именем isLoading. Но у вашего фактического сервиса есть property of typeObservable`` с именем isLoading, и это то, что ожидает ваш шаблон, отсюда и ошибка: асинхронному каналу нужен наблюдаемый объект в качестве входных данных, но вы передаете его isLoading, который является функцией в вашем тесте, и не наблюдаемый (посмотрите, как использование правильного типа помогает рассуждать об ошибках, которые вы получаете?).
Кстати, эта функция возвращает логическое значение true вместо Observable<boolean>
Вы можете определить простой объект вместо использования jasmine для создания своего поддельного сервиса:
const fakeService = {
isLoading: of(true)
}
Или вы можете использовать жасмин, но использовать его функцию spyOnProperty.
Или вы можете использовать BehaviorSubject<boolean> как тип isLoading и, таким образом, использовать реальную реализацию службы и просто заставить объект излучать true.
Немного дополнительной информации о создании объектов-шпионов Jasmine для поддельных сервисов со свойствами получения.
Чтобы создать шпионский объект с get-свойствами, методы и свойства нужно передать в конструктор отдельно:
createSpyObj('ExampleService’, { methods }, { get properties });
Пример
Следующая служба «Пример» имеет два метода и два свойства получения:
export class ExampleService {
// properties
public get exampleProperty1(): Observable<boolean> {
// implementation...
}
public get exampleProperty2(): Observable<Number> {
// implementation...
}
// methods
public exampleMethod1(): void {
// implementation...
}
public exampleMethod2(): void {
// implementation...
}
}
Создайте шпионский объект Jasmine для примерного сервиса следующим образом:
fakeExampleService = jasmine.createSpyObj<ExampleService>(
'FakeExampleService',
{
// pass in the methods here...
exampleMethod1: undefined,
exampleMethod2: undefined
},
{
// pass in the properties here...
exampleProperty1: of(false),
exampleProperty2: of(1),
}
);
спасибо, id тот же, вернул функцию вместо свойства