Home > database >  Angular 11 - Jest unit test methods in .then method
Angular 11 - Jest unit test methods in .then method

Time:01-20

I am running jest unit test in Angular 11, and I am trying to test methods in .then method.
But it seems that test methods have not run at expect method.

How should I write test code to wait until .then method ends?
I want to check idToken is set in localStorage in .then method.

Versions:

// package.json

"dependencies": {
    "@angular/animations": "~11.0.4",
    "@angular/cdk": "^11.2.2",
    "@angular/common": "~11.0.4",
    "@angular/compiler": "~11.0.4",
    "@angular/core": "~11.0.4",
    "@angular/forms": "~11.0.4",
    "@angular/material": "^11.2.2",
    "@angular/platform-browser": "~11.0.4",
    "@angular/platform-browser-dynamic": "~11.0.4",
    "@angular/router": "~11.0.4",
    ...
},
"devDependencies": {
    "@angular-builders/jest": "^12.1.2",
    "@angular-devkit/build-angular": "~0.1100.4",
    "@angular-jest/schematics": "0.2.0",
    "@angular/cli": "~11.0.4",
    "@angular/compiler-cli": "~11.0.4",
    "@angular/localize": "^11.0.0",
    "@types/jasmine": "~3.6.0",
    "@types/jest": "^26.0.24",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "jest": "^27.0.6",
    "jest-preset-angular": "^9.0.7",
    ...
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2"
}

Component Method:

// my-component.ts

signIn() {
  this.userService.fetchIdToken()  // return Promise(resolve => idToken)
    .then(idToken => {
      localStorage.setItem('idToken', idToken); // trying to test idToken is correctly set.
      ...
    });
}

Test Code:

// my-component.spec.ts

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  let loader: HarnessLoader;
  let userService: jest.Mocked<UserService>;
  const userServiceSpy = {} as UserServiceSpy;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [MyComponent],
      imports: [
        HttpClientTestingModule,
      ],
      providers: [
        { provide: ComponentFixtureAutoDetect, useValue: true },
        UserService,
      ],
    }).compileComponents();
    fixture = TestBed.createComponent(MyComponent);
    loader = TestbedHarnessEnvironment.loader(fixture);
    component = fixture.componentInstance;
    fixture.detectChanges();
    userService = TestBed.inject(UserService) as jest.Mocked<UserService>;
    userServiceSpy.fetchIdToken = jest.spyOn(userService, 'fetchIdToken');
  });

  describe('script', () => {
    
    describe('fetchIdToken', () => {
      it('ok', fakeAsync(() => {
        userServiceSpy.fetchIdToken.mockImplementation(() => 
          new Promise(() => 'idToken')
        );
        component.signIn();
        tick(); // wait until Promise is resolved. -> not working
        expect(userServiceSpy.signIn).toHaveBeenCalled(); // OK
        expect(localStorage.getItem('idToken')).toEqual('idToken'); // NG
      }));
    });

  });
});

Run Command:

$ jest --runInBand --watch

Result:

  ● MyComponent › script › fetchIdToken › ok

    expect(received).toEqual(expected) // deep equality

    Expected: "idToken"
    Received: null

      171 |         tick(); // wait until Promise is resolved. -> not working
      172 |         expect(userServiceSpy.fetchIdToken).toHaveBeenCalled();
    > 173 |         expect(localStorage.getItem('idToken')).toEqual('idToken');
          |                                                 ^
      174 |       }));
      175 |     });
      176 |   });

CodePudding user response:

If you want to mock the local storage in all your tests, declare it inside the beforeEach() function .

let localStore;

beforeEach(() => {
  localStore = {};

  spyOn(window.Storage.prototype, 'getItem').and.callFake((key) =>
    key in localStore ? localStore[key] : null
  );
});

or

let localStore;

beforeEach(() => {
  localStore = {};

  spyOn(window.localStorage, 'getItem').and.callFake((key) =>
    key in localStore ? localStore[key] : null
  );
});

CodePudding user response:

I think you need to modify mocking of token service to something like that:

    userServiceSpy.fetchIdToken.mockImplementation(() => 
      new Promise((resolve) => resolve('idToken'))
    );
  •  Tags:  
  • Related