Reputation: 1006
Below is my component function I want to write unit tests. I want to write a unit test to test the tokenRefresh
function in auth service is being called when getItem returns a string to the component.
Component.ts
refreshTokens(): void {
const refreshToken = this.localStorageService.getItem('refresh_token');
if (refreshToken) {
this.authService.tokenRefresh(refreshToken).subscribe({
next: (data: TokenModel) =>
this.authService.routeToDashboard(
data.access_token,
data.refresh_token,
data.expires_at
),
});
} else {
this.notificationService.openSnackBar('Please login again.');
}
}
localStorage.service.ts
@Injectable({
providedIn: 'root'
})
export class LocalStorageService {
constructor() { }
getItem(key: string): string | null {
return localStorage.getItem(key);
}
}
I have created mick services in my component.spec.ts to mock LocalStorageService and AuthService as below.
export class LocalStorageStub {
getItem(key: string): string | null {
return '7677673437437';
}
}
export class AuthorizeServiceStub {
tokenRefresh(key: string) {
return of({});
}
setItem(): void {
}
}
Below is my complete component.spec.ts.
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
let el: HTMLElement;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LoginComponent ],
imports: [
HttpClientModule,
RouterTestingModule,
MatSnackBarModule,
BrowserAnimationsModule
],
providers:[
{ provide: LocalStorageService, useClass: LocalStorageStub },
{ provide: AuthorizeService, useClass: AuthorizeServiceStub}
]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
});
it('should call token refresh if localstorage has refreshtoken', function() {
component.refreshTokens();
let service = fixture.debugElement.injector.get(LocalStorageService);
let authService = fixture.debugElement.injector.get(AuthorizeService);
service.getItem('key');
const setPageSpy2 = spyOn(authService, 'tokenRefresh');
expect(setPageSpy2).toHaveBeenCalled();
});
});
I get the below result for my test case.
Appreciate if someone can tell me what's the issue here.
Edit: The new order of unit test case
it('should call token refresh if localstorage has refreshtoken', function() {
let service = fixture.debugElement.injector.get(LocalStorageService);
let authService = fixture.debugElement.injector.get(AuthorizeService);
service.getItem('key');
component.refreshTokens();
const setPageSpy2 = spyOn(authService, 'tokenRefresh');
expect(setPageSpy2).toHaveBeenCalled();
});
Upvotes: 2
Views: 9467
Reputation: 1517
I did not find the problem, but I found a workaround :D
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
const authorizeServiceStub: AuthorizeService = jasmine.createSpyObj(
AuthorizeService,
{ 'tokenRefresh': of({}) },
);
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ LoginComponent ],
imports: [
HttpClientModule,
RouterTestingModule,
MatSnackBarModule,
BrowserAnimationsModule
],
providers:[
{ provide: LocalStorageService, useClass: LocalStorageStub },
{ provide: AuthorizeService, useValue: authorizeServiceStub },
]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
});
it('should call token refresh if localstorage has refreshtoken', function() {
let service = fixture.debugElement.injector.get(LocalStorageService);
service.getItem('key');
component.refreshTokens();
expect(authorizeServiceStub.tokenRefresh).toHaveBeenCalled();
});
});
Upvotes: 1