AngularM
AngularM

Reputation: 16648

Angular 2 Unit Test for a promise

I normally use fakeAsync to test a subscribe returning an observable. But on this rare occasion, I need to do the same but for a promise.

This is my attempt:

   //Service Stub:

  const testService = {
       testMethod: 
        jasmine.createSpy('testMethod').and.callFake(() => new Promise(() => 'test'))
  };

   it('test example',() => {
      // Arrange
      const response = 'test';
      component.selected = undefined;

      // Act
      component['myMethod']();

      //Assert
      expect(component.selected).toEqual(response);
    });

This is my actual code:

private myMethod(): void {
  return this.testService.testMethod()
    .then((response: string) => {
      this.selected = response;
    })
    .catch(error => this.logger.error(error, this));
}

Basically, need to know how to wait for "this.testService.testMethod" to return and set selected.

Currently, it's not waiting for the promise to return.

Note: I've updated my current attempt. But still got undefined in the expect.

Upvotes: 0

Views: 8565

Answers (2)

Nils Heumer
Nils Heumer

Reputation: 309

Actually I am unsure whether I understood your question correctly, but the usage of async and await might be a solution! See the sample below.

Class to Test

import { Router } from '@angular/router';
...

@Injectable({
  providedIn: 'root'
})
export class NavigationService {

  constructor(public router: Router) {
  }

  // Function to test. Note, that the routers navigate function returns a promise.
  navigateToAdminsLandingPage(): void  {
    this.router.navigate(['admin']).then();
  }

Testing a function that returns a mock promise

import ...

describe('NavigationService', () => {

  let testObj: NavigationService;
  
  // Test setup.
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ]
    });
    testObj = TestBed.get(NavigationHelperService);
  });

  // Testing a promise with async and await.
  it('should navigate to admin landing page', async () => {
    const spy = spyOn(testObj.router, 'navigate').and.returnValue(Promise.resolve(true));

    await testObj.navigateToAdminsLandingPage();

    expect(spy).toHaveBeenCalledTimes(1);
    expect(spy).toHaveBeenCalledWith(['admin']);
  });
});

Upvotes: 0

Scipion
Scipion

Reputation: 11888

You can try calling the tick() after the call

(see https://angular.io/guide/testing#the-fakeasync-function)

Upvotes: -2

Related Questions