2

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?

1 Answers1

2

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.

Amit Chigadani
  • 28,482
  • 13
  • 80
  • 98
  • But i need to know that it was called by component. And if i spy on smth, it will be never called by component? – Андрей Ефременков Aug 16 '18 at 07:20
  • I got other case: it("try to leave custom language with invalid form", async(() => { const componentService = fixture.debugElement.injector.get(NgbModal); let spyObj = spyOn(componentService, "open") component.switchDocumentLanguage("ru-Ru", {invalid: true}) fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); expect(spyObj).toHaveBeenCalled() }) })); – Андрей Ефременков Aug 16 '18 at 07:28
  • it goes to "switchDocumentLanguage" second 'if' where not called 'result' of mocked service 'open' method and it works fine, it has detected Spyed object. – Андрей Ефременков Aug 16 '18 at 07:28
  • If you donot add `and.callThrough()` to spy, then the `open()` wont be invoked. You can verify the difference. – Amit Chigadani Aug 16 '18 at 07:40
  • Well, you could also do `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. – Amit Chigadani Aug 16 '18 at 07:43