I'm trying to create a mock service so that after clicking on the form button, the click handler is called and subsequently a method from my mock service is called. What could be wrong here? Just started to deal with Jasmine.
My test:
describe('Login submit', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async () => {
TestBed.configureTestingModule({
providers: [
AuthService,
HttpClientTestingModule,
HttpClientModule,
HttpClient,
HttpHandler,
MatSnackBar,
Overlay,
FormBuilder,
],
});
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('authService should launch', () => {
let mockAuthService = jasmine.createSpyObj('AuthService', ['authUser']);
const mockUser = { usernsme: 'Marcus', password: 'Marcus#1' };
const compiled = fixture.debugElement;
const loginBtn = compiled.query(By.css('.login-btn')).nativeElement;
loginBtn.dispatchEvent(new Event('click'));
expect(mockAuthService).toHaveBeenCalled();
});
});
I made a test before this, where I manually pass the user into the method, but now I need everything to work on the button
function from login component:
userLoginClick() {
if (!this.form.valid) {
this.pushNotificationService.createNotification(
'Data format is incorrect'
);
return false;
}
const user = {
username: this.form.controls['username'].value,
password: this.form.controls['password'].value,
};
this.authService.authUser(user);
}
function from auth service:
authUser(user: User) {
return this.http
.post(
`${environment.domain}${BackendRoutes.Login}`,
user,
this.httpOptions
)
.subscribe((data: any) => {
if (!data.success) {
this.pushNotificationService.createNotification(data.message);
} else {
this.router.navigate([`/${Paths.Lobby}`]);
this.storeUser(data.token, data.user);
}
});
}
CodePudding user response:
Make the following changes, follow the comments with '!!' and explanations.
describe('Login submit', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
// !! Create mockAuthService here !!
let mockAuthService: jasmine.SpyObj<AuthService>;
beforeEach(async () => {
// !! Create mock in a before each so we have a fresh mock for each test.
mockAuthService = jasmine.createSpyObj<AuthService>('AuthService', ['authUser']);
TestBed.configureTestingModule({
providers: [
// !! Provide mocked AuthService instead of the real one for the tests
{ provide: AuthService, useValue: mockAuthService },
HttpClientTestingModule,
HttpClientModule,
HttpClient,
HttpHandler,
MatSnackBar,
Overlay,
FormBuilder,
],
});
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('authService should launch', () => {
// !! Get rid of this line, we don't need it anymore.
// let mockAuthService = jasmine.createSpyObj('AuthService', ['authUser']);
const mockUser = { usernsme: 'Marcus', password: 'Marcus#1' };
const compiled = fixture.debugElement;
const loginBtn = compiled.query(By.css('.login-btn')).nativeElement;
loginBtn.dispatchEvent(new Event('click'));
// !! Change this line to mockAuthService.authUser (it should be the method and not the object).
expect(mockAuthService.authUser).toHaveBeenCalled();
});
});
This is a good resource in learning unit testing with Angular: https://testing-angular.com/.