0

I have an async method where I am calling 2 other methods that return promise. I am mocking uploadData and addOrEdit to return a resolved promise. When I call the uploadFile, both uploadData and addOrEdit methods get covered, but the expectation, that says addOrEdit have been called fails. I am using Angular 9 with Jest.

Here's the code:

Method to be tested:

 async uploadFile(): Promise<void> {
    
      let uploadedLeis: Lei[] = [];
      this.onNoClick(); // closeing the upload dialog
    
      try {
        const { leis, errors } = await this._fileService.uploadData(
          this.files[0],
        );
    
        try {
          uploadedLeis = await this._lei.addOrEdit(leis);
    
          if (!this._util.isEmpty(uploadedLeis)) {
            this._lei.updateLocalData(uploadedLeis);
    
            if (this._util.isEmpty(errors)) {
              this._notification.notifySuccess(
                `File was successfully uploaded with ${uploadedLeis.length} LEI(s)`,
              );
            } else {
              this._notification.notifySuccess(
                `File was successfully uploaded with ${uploadedLeis.length} LEI(s).\nThere were ${errors.length} errors in the file`,
                'View Errors',
              );
            }
          } else {
            this._notification.notifyError(`No records were updated`);
          }
        } catch (err) {
          this._notification.notifyError(
            `Sorry!! Failed to update records from the file`,
            err,
          );
        }
      } catch (err) {
        this._notification.notifyError(
          `Sorry!! Problem occured while reading the file\n${err.error}`,
          err,
        );
      } finally {
        this.files = [];
      }
    }

test case

it(`test description`, fakeAsync(() => {
  const spy1 = jest.spyOn(component, 'onNoClick');
  const spy2 = jest.spyOn(fileService, 'uploadData').mockResolvedValue({
    leis: [],
    errors: [],
  });
  const spy3 = jest.spyOn(leiService, "addOrEdit").mockResolvedValue({});

  component.fileUploaded = true;
  component.files = event;

  fixture.detectChanges();

  component.uploadFile();

  flush();
  expect(spy1).toBeCalled();     // passes
  expect(spy2).toBeCalled();    // passes
  expect(spy3).toBeCalled();   // fails
}));
skyboyer
  • 22,209
  • 7
  • 57
  • 64
Pritam Bohra
  • 3,912
  • 8
  • 41
  • 72

1 Answers1

0

Try using tick or flushMicrotasks to resolve the promises before carrying forward with your assertions. I think flush() only forwards time and not promises. It may be possible to replace all flushMicrotasks with just tick but I am not sure.

Something like this:

import { flushMicrotasks } from '@angular/core/testing';


it(`test description`, fakeAsync(() => {
  const spy1 = jest.spyOn(component, 'onNoClick');
  const spy2 = jest.spyOn(fileService, 'uploadData').mockResolvedValue({
    leis: [],
    errors: [],
  });
  const spy3 = jest.spyOn(leiService, "addOrEdit").mockResolvedValue({});

  component.fileUploaded = true;
  component.files = event;

  fixture.detectChanges();

  component.uploadFile();

  flushMicrotasks();
  expect(spy1).toBeCalled();     // passes
  flushMicrotasks();
  expect(spy2).toBeCalled();    // passes
  flushMicrotasks();
  expect(spy3).toBeCalled();   // fails
}))
AliF50
  • 16,947
  • 1
  • 21
  • 37