Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Error: <toHaveBeenCalled> : Expected a spy, but got Object({ authUser: spy on AuthService.authUser }). Usage: expect(<spyObj>).toHaveBeenCalled()

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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);
        }
      });
  }

>Solution :

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/.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading