Issue
I'm writing a simple standalone Logout component test using a service depending on HttpClient. I tried different solutions to just stub the HttpAuthService and every solution I tried so far all throw :
NullInjectorError: R3InjectorError(Standalone[LogoutComponent])[HttpAuthService -> HttpAuthService -> HttpClient -> HttpClient]: NullInjectorError: No provider for HttpClient!
The service I try to stub:
@Injectable({
providedIn: 'root'
})
export class HttpAuthService implements AuthService {
private userSignal = signal<User|null>(null);
private backendURL = environment.backendURL;
public user = computed<User | null>(this.userSignal);
constructor(private httpClient: HttpClient) {
}
login(params: { email: string; password: string }): Observable<void> {
return this.httpClient.get<any[]>(`${this.backendURL}/users?email=${params.email}`)
.pipe(
tap(result=> {
if (result.length > 0) {
this.userSignal.set({userName: result[0].email})
}
}),
map( result => {
if (result.length == 0) {
throw new Error('User not found');
} else {
return undefined;
}
})
)
}
logout(): void {
this.userSignal.set(null);
}
}
The Logout component:
@Component({
selector: 'app-logout',
standalone: true,
imports: [MatButtonModule, MatIconModule],
template: `
<button mat-icon-button (click)="onLogout()" >
<mat-icon>logout</mat-icon>
</button>
`,
styles: ``
})
export class LogoutComponent {
constructor(private authService: HttpAuthService) {
}
onLogout() {
this.authService.logout();
}
}
The Logout unittest:
describe('LogoutComponent', () => {
let component: LogoutComponent;
let fixture: ComponentFixture<LogoutComponent>;
const fakeAuthService = new AuthStub();
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [LogoutComponent],
providers: [{provide: HttpAuthService, useClass: AuthStub}]
})
.compileComponents();
fixture = TestBed.createComponent(LogoutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
export class AuthStub implements AuthService {
login(params: { email: string; password: string }): Observable<void> {
return of(undefined);
}
logout(): void {
}
}
Solution tried:
- Using jasmine.createSpyObj('', {//login and logout defined}) and added to providers with {provide/useValue}
- Using AuthStub as coded below, created a const with a new instance and and added to providers with {provide/useValue}
- Using AuthStub as coded below, created a const with a new instance and and added to providers with {provide/useClass}
To rule out IDE (Webstorm) I also runned the test in terminal with ng test. Test setup is using default ng Karma/jasmine test setup with Playwright for e2e testing.
Solution
Could you try this code, I think since its standalone component, it needs to be instantiated differently!
describe('LogoutComponent', () => {
let component: LogoutComponent;
let fixture: ComponentFixture<LogoutComponent>;
beforeEach(async () => {
fixture = await render(LogoutComponent, {
providers: [
{
provide: HttpAuthService,
useValue: {
logout: () => { }
}
}
]
});
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
Answered By - Naren Murali
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.