Search code examples
angularjasminetestbed

TestBed mocking service


I got component to test with method:

     switchDocumentLanguage(lang, formData):any {
        if (lang === this.currentLang) {
          return null;
        }
        if (formData.invalid && this.currentLang === this.appConfig.defaultLanguage ||
          !this.documentFormData.content && this.currentLang === this.appConfig.defaultLanguage) {

          return this.modalService.open(this.setDefaultModal);

        }

        //(2*)
        if (formData.invalid || !this.documentFormData['content']) {
          return this.modalService.open(this.tabSwitchModal).result.then(() => {
            this.fillFormData(lang);
          }, (reason) => {
          });
        } else {
          return this.fillFormData(lang);
        }
      }

It falls to condition marked (2*)

In test i use stub class ModalService:

    class ModalService {
      open(someArg?: any){
        return {result : Promise.resolve('success')};
      }
    }

    const appConfig =
    {
      defaultLanguage: 'en-US'
    }

and my test config looks like:

 describe('document.edit component test', () => {

  let component: DocumentEditComponent;
  let fixture: ComponentFixture<DocumentEditComponent>;

  beforeEach(() => {

    TestBed.configureTestingModule({
      imports: [FormsModule],

      schemas: [NO_ERRORS_SCHEMA],
      declarations: [DocumentEditComponent],
      providers: [{provide: AppConfig, useValue: appConfig},
        {provide: DocumentsService, useValue: documentsService},
        {provide: NgbModal, useClass: ModalService},
        {provide: ActivatedRoute, useValue: activatedRoute},
        {provide: BaThemeSpinner, useValue: loader},
        {provide: PopupResultService, useValue: popupResultService},
      ],
    })
  });

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

and here is the test that gives me error:

  it("try to leave custom language with invalid form", async(() => {
      const componentService = fixture.debugElement.injector.get(NgbModal);

      let spyObj = spyOn(componentService, "open")

      component.documentFormData.content = "some test values";
      component.currentLang = "es-VE";


      fixture.detectChanges();
      component.switchDocumentLanguage("ru-Ru", {invalid: true})
      fixture.detectChanges();

      fixture.whenStable().then(() => {
        fixture.detectChanges();
        expect(spyObj).toHaveBeenCalled()
      })
    }));

Error text :

document.edit component test try to leave custom language with invalid form
Failed: Cannot read property 'result' of undefined
TypeError: Cannot read property 'result' of undefined

It looks like my stub class "ModalService" doesn't return anything, i tried to place there console.log() but it never appear. Is anyone has come across with similar?


Solution

  • It is not being called because you have a spy on it.

    Probably what you could do is, extend the spy with callThrough()

    let spyObj = spyOn(componentService, "open").and.callThrough();
    

    EDIT :

    You could also do it using returnValue()

    let spyObj = spyOn(componentService, "open").and.returnValue({result : Promise.resolve('success')}); 
    

    In this case open() wont be called, instead you will return the same result that is returned by mock Class method. You will not need mock Class too if you use this.