Tom
Tom

Reputation: 8691

Jasmine test : Expected a SPY but got a Function error

I have written a test for angular component using Jasmine and getting error . I basically want to test if loadPersonNotes is called when ngOnchanges is called

ComplianceNoteComponent should call getPersonNote FAILED
        Error: <toHaveBeenCalled> : Expected a spy, but got Function.
        Usage: expect(<spyObj>).toHaveBeenCalled()
            at <Jasmine>

I am not sure why it is complaining

Jasmine Test

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { of, Observable } from 'rxjs';
import { configureTestSuite } from 'ng-bullet';
import { DxButtonModule } from 'devextreme-angular';
import { NgxPermissionsModule } from 'ngx-permissions';

import { SharedFontAwesomeModule } from '../../../../shared/shared-font-awesome.module';
import { UserService } from '../../../../shared/services/user.service';
import { ComplianceNoteComponent } from './compliance-note.component';
import { IPersonNote } from '../../../../shared/models/IPersonNote';
import { IUser } from '../../../../shared/models/IUser';
import { nameof } from '../../../../shared/helpers/nameof';



describe('ComplianceNoteComponent', () => {
  let component: ComplianceNoteComponent;
  let fixture: ComponentFixture<ComplianceNoteComponent>;

  const mockPersonNote = <IPersonNote>{
    authorId : 12,
    id : 1,
    personId : 101,
    note : 'This is a test note ',
    authorName: 'xys',
    createdBy: 'ABC',
    createdDate : new Date()
  };

  const mockUserService: UserService = <UserService>{
    getCurrentUser() {
      return <IUser>{ id: 1 };
    },
    getPersonNote(id: 1) { 
      return of ({}); }
  };

  configureTestSuite((() => {
    TestBed.configureTestingModule({
      imports: [DxButtonModule, SharedFontAwesomeModule, NgxPermissionsModule.forRoot()],
      declarations: [ComplianceNoteComponent],
      providers: [
        { provide: UserService, useValue: mockUserService }
      ]
    });
  }));

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ComplianceNoteComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ComplianceNoteComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should call getPersonNote', () => {
    spyOn(mockUserService, 'getPersonNote').and.returnValue(of(mockPersonNote)).and.callThrough();
    component.ngOnChanges();
    expect(component.loadPersonNotes).toHaveBeenCalled();
  });

});

Component

import { UserService } from 'src/app/shared/services/user.service';
import { IPersonNote } from 'src/app/shared/models/IPersonNote';

@Component({
  selector: 'app-compliance-note',
  templateUrl: './compliance-note.component.html',
  styleUrls: ['./compliance-note.component.scss']
})
export class ComplianceNoteComponent implements OnChanges {
  @Input() id: number;
  public personNotes: IPersonNote;
  public isCurrentUser = false;

  constructor(  private userService: UserService) { }

  ngOnChanges() {
    this.loadPersonNotes();
  }


  loadPersonNotes() {
    this.isCurrentUser = this.id !== this.userService.getCurrentUser().id;
    this.userService.getPersonNote(this.id).subscribe((x: IPersonNote) => {
      this.personNotes = x;
    });
  }

}

UserService

    public getPersonNote = (id: number): Observable<IPersonNote> =>
    this.http.get<IPersonNote>(`${this.baseUrl}person-note/${id}`)  


export interface IPersonNote {
    id: number;
    personId: number;
    note: string;
    authorId: number;
    authorName: string;
    createdBy: string;
    createdDate: Date;
}   

Upvotes: 6

Views: 11152

Answers (1)

uminder
uminder

Reputation: 26190

The problem is that the following expect expects a spy but you provide class method component.loadPersonNotes.

expect(component.loadPersonNotes).toHaveBeenCalled();

To make this work, you need to create a spy on component.loadPersonNotes method prior to invoke component.ngOnChanges.

spyOn(component, 'loadPersonNotes');
component.ngOnChanges();
expect(component.loadPersonNotes).toHaveBeenCalled();

According to the test description, you however want to verify that getPersonNote from the UserService is invoked. Therefore, you probably have to reconsider your expect.

Upvotes: 8

Related Questions