Мне трудно отладить, почему моя страница ioni c жалуется на то, что AuthService не имеет поставщика хранилища. Я попытался создать новый AuthService в TestBed, но без кубиков. Не могли бы вы также объяснить, почему это проблема, чтобы я мог извлечь из нее урок? Я ничего не могу найти о внедрении службы, которая вводит модуль хранения.
Ошибка: StaticInjectorError (DynamicTestModule) [AuthService -> Storage]: StaticInjectorError (Platform: core) [AuthService -> Storage ]: NullInjectorError: Нет провайдера для хранилища!
import {
async,
ComponentFixture,
TestBed,
fakeAsync,
tick,
} from '@angular/core/testing';
import { IonicModule } from '@ionic/angular';
import { RouterTestingModule } from '@angular/router/testing';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import {
HttpClientTestingModule,
HttpTestingController,
} from '@angular/common/http/testing';
import { SignInPage } from './sign-in.page';
import { User } from 'src/app/classes/user';
import { AuthService } from '../../services/auth-service/auth.service';
import { UsersDataPublic } from '../../services/users-service/users-data-public';
import { UserProfileService } from '../../services/user-profile/user-profile.service';
import { UserProfileDatabase } from '../../services/user-profile/user-profile-db.service';
import { AppConstants } from '../../constants/app.constants';
import { Storage } from '@ionic/Storage';
import { NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA, inject } from '@angular/core';
const storageIonicMock: any = {
get: () => new Promise<any>((resolve, reject) => resolve('As2342fAfgsdr')),
set: () => new Promise<any>((resolve, reject) => resolve('As2342fAfgsdr'))
};
describe('SignInPage', () => {
let component: SignInPage;
let httpTestingController: HttpTestingController;
let fixture: ComponentFixture<SignInPage>;
let httpClient: HttpClient;
let service: UsersDataPublic;
let userProfileservice: UserProfileService;
let authService: AuthService;
let auth;
let userProfileDatabase: UserProfileDatabase;
let constants: AppConstants;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [SignInPage],
providers: [
UsersDataPublic,
UserProfileService,
UserProfileDatabase,
AppConstants,
AuthService,
{
provide: Storage,
useValue: storageIonicMock
}
],
imports: [
IonicModule.forRoot(),
ReactiveFormsModule,
FormsModule,
RouterTestingModule,
FormsModule,
HttpClientTestingModule,
],
schemas: [NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA],
}).compileComponents();
fixture = TestBed.createComponent(SignInPage);
constants = TestBed.get(AppConstants);
service = TestBed.get(UsersDataPublic);
userProfileservice = TestBed.get(UserProfileService);
authService = TestBed.get(new AuthService(storageIonicMock, httpClient, constants));
userProfileDatabase = TestBed.get(UserProfileDatabase);
httpClient = TestBed.get(HttpClient);
httpTestingController = TestBed.get(HttpTestingController);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it('should create', () => {
expect(component).toBeTruthy();
});
it('form invalid when empty', () => {
expect(component.signinForm.valid).toBeFalsy();
});
it('should run ngOnInit 1 time', fakeAsync(() => {
fixture.detectChanges();
spyOn(component, 'ngOnInit').and.callThrough();
component.ngOnInit();
tick(); // simulates the passage of time until all pending asynchronous activities finish
fixture.detectChanges();
expect(component.ngOnInit).toHaveBeenCalledTimes(1);
}));
it('should have a title of Sign In', () => {
const title: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#home-title'
);
expect(title.textContent).toEqual('Sign In');
});
it('should run signIn 1 time', fakeAsync(() => {
fixture.detectChanges();
spyOn(component, 'signIn').and.callThrough();
component.signIn();
tick(); // simulates the passage of time until all pending asynchronous activities finish
fixture.detectChanges();
expect(component.signIn).toHaveBeenCalledTimes(1);
}));
it('should set the user object to the values set by signIn', fakeAsync(() => {
const user = {
ppsn: '13322277P',
day: '1',
month: '1',
year: '1970',
password: 'Testing123!',
};
let ppsn: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#ppsn'
);
let day: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#day'
);
let month: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#month'
);
let year: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#year'
);
let password: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#password'
);
ppsn.value = '13322277P';
day.value = '1';
month.value = '1';
year.value = '1970';
password.value = 'Testing123!';
fixture.detectChanges();
spyOn(component, 'signIn').and.callThrough();
component.signIn();
tick(); // simulates the passage of time until all pending asynchronous activities finish
fixture.detectChanges();
expect(component.signIn).toHaveBeenCalledTimes(1);
expect(component.userDetails).toEqual(user);
}));
it('should not match the user object to the values set by signIn', fakeAsync(() => {
const user = {
ppsn: '13322277P',
day: '1',
month: '2',
year: '1970',
password: 'Testing123!',
};
let ppsn: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#ppsn'
);
let day: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#day'
);
let month: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#month'
);
let year: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#year'
);
let password: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
'#password'
);
ppsn.value = '13322277P';
day.value = '1';
month.value = '1';
year.value = '1970';
password.value = 'Testing123!';
fixture.detectChanges();
spyOn(component, 'signIn').and.callThrough();
component.signIn();
tick(); // simulates the passage of time until all pending asynchronous activities finish
fixture.detectChanges();
expect(component.signIn).toHaveBeenCalledTimes(1);
expect(component.userDetails).not.toEqual(user);
}));
});
AuthService, который вводит хранилище
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { catchError } from 'rxjs/operators';
import { throwError, Observable, BehaviorSubject } from 'rxjs';
import { AppConstants } from '../../constants/app.constants';
import { Storage } from '@ionic/storage';
@Injectable({
providedIn: 'root'
})
export class AuthService {
authenticationState = new BehaviorSubject(false);
authDetails = {authenticated: false, type: null, myAccountPortalAuthenticated: false };
constructor(private storage: Storage, private httpClient: HttpClient, private constants: AppConstants) { }
handleError(error: HttpErrorResponse) {
let errorMessage = 'Unknown error!';
if (error.error instanceof ErrorEvent) {
errorMessage = `Error: ${error.error.message}`;
} else {
errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
}
return throwError(errorMessage);
}
login(url): Observable<any> {
return this.httpClient.post(url, {})
.pipe(
catchError((err: HttpErrorResponse) => {
return throwError(err);
})
);
}
devLogin(url): Observable<any> {
return this.httpClient.get(this.constants.LOCAL_REST_API_SERVER + '/users')
.pipe(
catchError((err: HttpErrorResponse) => {
return throwError(err);
})
);
}
logout(url): Observable<any> {
return this.httpClient.post(url, {})
.pipe(
catchError((err: HttpErrorResponse) => {
return throwError(err);
})
);
}
getAuthenticationDetails() {
return this.storage.get('auth');
}
getAuthenticationState(): Observable<boolean> {
return this.authenticationState.asObservable();
}
setIsAuthenticated(value, loginType) {
this.authDetails.authenticated = value;
this.authDetails.type = loginType;
this.storage.set('auth', this.authDetails);
this.authenticationState.next(value);
}
}
Модуль для входа
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { UserProfileDatabase } from '../../services/user-profile/user-profile-db.service';
import { UserProfileService } from '../../services/user-profile/user-profile.service';
import { AuthService } from '../../services/auth-service/auth.service';
import { SignInPageRoutingModule } from './sign-in-routing.module';
import { SignInPage } from './sign-in.page';
import { ReactiveFormsModule } from '@angular/forms';
import { Storage, IonicStorageModule } from '@ionic/Storage';
@NgModule({
imports: [
CommonModule,
FormsModule,
IonicModule,
SignInPageRoutingModule,
ReactiveFormsModule,
IonicStorageModule.forRoot()
],
declarations: [SignInPage],
providers: [UserProfileDatabase, UserProfileService, AuthService]
})
export class SignInPageModule {}