#angular #jestjs #adal #jsdom #jest-preset-angular
#angular #jestjs #adal #jsdom #jest-preset-angular
Вопрос:
Помогите мне, пожалуйста.
Я перехожу на Jest для запуска модульных тестов ANGULAR, но при выполнении я получаю сообщение об ошибке:
Не удалось запустить набор тестов src/app/modules/dashboard/components/navbar/navbar.component.spec.ts
ReferenceError: AuthenticationContext is not defined 6 | 7 | declare var AuthenticationContext: adal.AuthenticationContextStatic; > 8 | const createAuthContextFn: adal.AuthenticationContextStatic = AuthenticationContext; | ^ 9 | 10 | @Injectable() 11 | export class AdalService { at Object.<anonymous> (src/app/core/authentication/adal.service.ts:8:63) at Object.<anonymous> (src/app/core/authentication/adal-access.guard.ts:3:1) at Object.<anonymous> (src/app/modules/dashboard/components/navbar/navbar.component.spec.ts:5:1)
Наборы тестов: 1 сбой, всего 1
Adal.service.ts не работает для меня в angular, когда я запускаю тесты с помощью Jest.
когда я запускаю с Karma, это работает
Это ТЕСТ:
import { Store } from '@ngrx/store';
import { RouterTestingModule } from '@angular/router/testing';
import { MatMenuModule } from '@angular/material/menu';
import { AdalConfigService } from './../../../../core/authentication/adal-config.service';
import { AdalAccessGuard } from './../../../../core/authentication/adal-access.guard';
import { AdalService } from '@authentication/adal.service';
import { environment } from '@env/environment';
import { APP_CONFIG } from '@app/app.config';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NavbarComponent } from './navbar.component';
describe('NavbarComponent', () => {
let component: NavbarComponent;
let fixture: ComponentFixture<NavbarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [NavbarComponent],
imports: [
RouterTestingModule,
MatMenuModule
],
providers: [
{
provide: Store,
useValue: {
dispatch: jest.fn(),
pipe: jest.fn()
}
},
AdalService,
AdalConfigService,
AdalAccessGuard,
{
provide: APP_CONFIG, useValue: {
apiEndpoint: environment.apiEndPoint,
clientId: environment.azureActiveDirectory.clientId,
tenantId: environment.azureActiveDirectory.tenantId,
resource: environment.azureActiveDirectory.resource,
redirectUri: environment.azureActiveDirectory.redirectUri
}
}]
})
.compileComponents();
}));
beforeEach(() => {
let mockAdalError;
let mockAdal;
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;
mockAdalError = false;
mockAdal = {
userName: 'xxx',
profile: {
aud: 'xxx',
}
};
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
- КОМПОНЕНТ ПРОТЕСТИРОВАН:
import { AdalService } from '@authentication/adal.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
public name;
public surname;
public email;
constructor( private adalService: AdalService ) { }
ngOnInit() {
this.loadUserInfo(this.adalService.userInfo);
}
onLogout(): void {
this.adalService.logout();
}
loadUserInfo(adalUser: any): void {
if (adalUser) {
this.name = XXX;
this.email = XXX;
} else {
this.name = 'No disponible';
this.email = 'No disponible';
}
}
}
Это СЕРВИС ADAL:
import { Injectable } from '@angular/core';
import { Observable, Subscriber } from 'rxjs';
import { retry } from 'rxjs/operators';
import { AdalConfigService } from './adal-config.service';
import { adal } from 'adal-angular';
declare var AuthenticationContext: adal.AuthenticationContextStatic;
const createAuthContextFn: adal.AuthenticationContextStatic = AuthenticationContext;
@Injectable()
export class AdalService {
private context: adal.AuthenticationContext;
constructor(private configService: AdalConfigService) {
this.context = new createAuthContextFn(configService.adalSettings);
}
login() {
this.context.login();
}
logout() {
this.context.logOut();
}
get authContext() {
return this.context;
}
handleWindowCallback() {
this.context.handleWindowCallback();
}
public get userInfo() {
return this.context.getCachedUser();
}
public get accessToken() {
return this.context.getCachedToken(this.configService.adalSettings.clientId);
}
public get isAuthenticated() {
return this.userInfo amp;amp; this.accessToken;
}
public isCallback(hash: string) {
return this.context.isCallback(hash);
}
public getLoginError() {
return this.context.getLoginError();
}
public getAccessToken(endpoint: string, callbacks: (message: string, token: string) => any) {
return this.context.acquireToken(endpoint, callbacks);
}
public acquireTokenResilient(resource: string): Observable<any> {
return new Observable<any>((subscriber: Subscriber<any>) =>
this.context.acquireToken(resource, (message: string, token: string) => {
token ? subscriber.next(token) : subscriber.error(message);
})
).pipe(retry(3));
}
}
Я использую версию: «adal-angular»: «^ 1.0.17»,
Комментарии:
1. Можете ли вы также поделиться своим протестированным компонентом?
2. Спасибо, я уже добавил его в начальный пост. С наилучшими пожеланиями
3. И можете ли вы поделиться AdalService? Где вы создаете экземпляр AuthenticationContext?
4. Это в конце сообщения, спасибо
Ответ №1:
Решение вашей проблемы
Чтобы ваша настройка прошла гладко, вы должны инициализировать AuthenticationContext где-то глобально. Я предполагаю, что это происходит в браузере в вашем коде путем загрузки некоторого скрипта adal в ваш index.html
или polyfills.ts
.
Jest не загружает эти файлы и, следовательно, нигде не инициализирует AuthenticationContext.
Своим объявлением переменной declare var AuthenticationContext: adal.AuthenticationContextStatic
вы сообщаете TypeScript: «Я гарантирую, что я инициализирую эту переменную глобально где-то в другом месте», но, похоже, вы не делаете это здесь в шутку.
Решением было бы либо импортировать скрипт, который инициализирует AuthenticationContext в тестовых файлах, где это требуется, либо сделать это вручную в файлах, где требуется:
// 1. Initialize Variable
// not sure if you can initialize it like this, see the adal docs or source code
globalThis.AuthenticationContext = new AuthenticationContext();
// 2. Tell TypeScript compiler about this variable
declare const AuthenticationContext: adal.AuthenticationContextStatic;
Модульное тестирование
Вы говорите о модульных тестах, но ваши тесты на самом деле не похожи на модульные тесты, поскольку вы не тестируете их изолированно.
Если вы хотите протестировать каждый компонент по единицам, вам вообще не следует создавать экземпляр AuthenticationContext для тестирования панели навигации. Все остальные компоненты и объекты, которые поступают не изнутри панели навигации, должны быть издевательски обработаны и предоставлены как фиктивные объекты. Это также косвенно решит вашу проблему.
Чтобы лучше понять это, ознакомьтесь с руководством по тестированию Angular и документацией jest .
Приветствия и счастливого кодирования!