Проблема
Я пытаюсь написать spe c в жасмине для службы Angular, которая у меня есть. Служба упаковывает @azure/msal-angular
, а также использует Microsoft Graph API для получения авторизованного изображения профиля пользователя. У меня проблемы с получением теста для успеха. Все, что я пытаюсь сделать, - это убедиться, что при возникновении ошибки Graph API при запросе изображения (т. Е. Возникает ошибка 404), эта ошибка обнаруживается, и вместо этого возвращается изображение по умолчанию из моей папки ресурсов.
Тем не менее, я получаю следующую ошибку: ![enter image description here](https://i.stack.imgur.com/MnfDj.png)
Ниже тестируется моя служба и сам тест. Мы ценим любую помощь!
Сервис
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { BroadcastService, MsalService } from '@azure/msal-angular';
import { Account, AuthError, AuthResponse, ClientAuthError } from 'msal';
import { Observable, ReplaySubject, throwError } from 'rxjs';
import { catchError, map, shareReplay, switchMap } from 'rxjs/operators';
import { GraphUser } from '../../models';
import { LocalBlobService } from '../../services';
import { environment } from './../../../environments/environment';
@Injectable({
providedIn: 'root',
})
export class AuthService {
isLoggedIn: boolean;
/** TODO: Cache locally
* - clear on logout
* - how often to refresh?
*/
graphUser$: Observable<GraphUser>;
/** TODO: Cache locally
* - clear on logout
* - how often to refresh?
*/
graphPicture$: Observable<SafeUrl>;
get loginFailure$(): Observable<any> {
return this._loginFailure$.asObservable();
}
get loginSuccess$(): Observable<any> {
return this._loginSuccess$.asObservable();
}
get user(): Account {
const user = this._msal.getAccount();
this.isLoggedIn = !!user;
return user;
}
private _loginFailure$ = new ReplaySubject<any>();
private _loginSuccess$ = new ReplaySubject<any>();
constructor(
private readonly _http: HttpClient,
private readonly _msal: MsalService,
private readonly _broadcasts: BroadcastService,
private readonly _sanitizer: DomSanitizer,
private readonly _localBlob: LocalBlobService
) {
this._msal.handleRedirectCallback(this.redirectCallback);
this.getGraphUserInfo();
this._broadcasts.subscribe(
'msal:loginFailure',
this.loginFailureCallback
);
this._broadcasts.subscribe(
'msal:loginSuccess',
this.loginSuccessCallback
);
}
updateUserProfilePhoto(file) {
return this._http
.put(environment.AD.pictureUrl, file)
.pipe(
catchError((error, caught) => this.handlePictureError(error))
);
}
private getGraphUserInfo() {
if (this.user) {
this.graphUser$ = this.getGraphUser();
this.graphPicture$ = this.getGraphPicture();
}
}
private getGraphPicture(): Observable<SafeUrl> {
return this._http
.get(environment.AD.pictureUrl, {
responseType: 'blob',
})
.pipe(
catchError((error, caught) => this.handlePictureError(error)),
switchMap(blob => this._localBlob.readAsDataURL(blob)),
map(picture => this._sanitizer.bypassSecurityTrustUrl(picture)),
shareReplay(1)
);
}
private getGraphUser(): Observable<GraphUser> {
return this._http.get<GraphUser>(environment.AD.graphUrl).pipe(
catchError((error, caught) => throwError(error)),
shareReplay()
);
}
private loginSuccessCallback = payload => {
this.isLoggedIn = true;
this._loginSuccess$.next();
this.getGraphUserInfo();
};
private loginFailureCallback = payload => {
this.isLoggedIn = false;
this._loginFailure$.next();
};
private redirectCallback = (
redirectError: AuthError,
redirectResponse: AuthResponse
) => {
if (redirectError) {
console.error(redirectError);
return;
}
console.log(redirectResponse);
};
private handlePictureError(error: ClientAuthError): Observable<Blob> {
console.log(error);
return this._http.get('/assets/images/defaultAvatarSmall.png', {
responseType: 'blob',
});
}
}
Тест
it('should return default image if graph API picture fails', (done: DoneFn) => {
// Arrange
const spy = spyOn(TestBed.inject(HttpClient), 'get')
.withArgs(environment.AD.graphUrl)
.and.callThrough()
.withArgs(environment.AD.pictureUrl, {
responseType: 'blob',
} as any)
.and.returnValue(throwError(new ClientAuthError('')))
.withArgs('/assets/images/defaultAvatarSmall.png', {
responseType: 'blob',
} as any)
.and.callThrough();
// Act
const service: AuthService = TestBed.inject(AuthService);
service.graphPicture$.subscribe(
() => {
// Assert
expect(spy.calls.allArgs()).toEqual([
[environment.AD.graphUrl],
[
environment.AD.pictureUrl,
{ responseType: 'blob' as 'json' },
],
[
'/assets/images/defaultAvatarSmall.png',
{ responseType: 'blob' as 'json' },
],
]);
done();
},
error => {
expect(1).toEqual(1);
done();
}
);
});