Home > database >  How to test Angular Router Resolve methed?
How to test Angular Router Resolve methed?

Time:10-09

I need to write unit test to Angular Router resolver. I wrote a unit test for creation, but I don't know how to test the return value and got stuck in it.

Resolver that used for getting info for component

@Injectable
export class InfoResolver implements Resolve<any> {
  constructor(private readonly http: HttpClient, private readonly store: Store<IAppState>) {}

  resolve(route: ActivatedRouteSnapshot): any {
    const a$ = this.store.pipe(select(a));
    const b$ = this.store.pipe(select(b));

    return combineLatest([a$, b$]).pipe(
      take(1),
      map(([a, b]) => {
        return a && !(b && route.paramMap.get(id) === 2)
          ? this.http.get('/url')
          : of(false)      
        })
    )
  }
}

Unit test for creation of the resolver

const state = {
  a: true,
  b: false
}

describe('InfoResolver', () => {
  let resolver: InfoResolver
  let route = {
    paramMap: {
      get: (id) => 1
    }
  }

  beforeEach(async() => {
    TestBed.configureTestingModule({
      providers: [InfoResolver, provideMockStore({ state })]
    })

    resolver = TestBed.inject(InfoResolver)
  })

  it('should create', () => {
    expect(resolver).toBeTruthy()
  })
})

How can I test the return value of resolve method?

CodePudding user response:

You should import HttpClientTestingModule if you're injecting HttpClient so you don't actually make Http calls in your unit test.

To unit test, I would directly call the resolve method and subscribe to it as shown in the 2nd test.

import { HttpClientTestingModule } from '@angular/common/http/testing';
....
const state = {
  a: true,
  b: false
}

describe('InfoResolver', () => {
  let resolver: InfoResolver
  let route = {
    paramMap: {
      get: (id) => 1
    }
  }

  beforeEach(async() => {
    TestBed.configureTestingModule({
      // add this to imports array
      imports: [HttpClientTestingModule],
      providers: [InfoResolver, provideMockStore({ state })]
    })

    resolver = TestBed.inject(InfoResolver)
  })

  it('should create', () => {
    expect(resolver).toBeTruthy()
  })

  // new test
  it('should return xyz if abc', (done: DoneFn) => {
    resolver.resolve(route).subscribe(result => {
      expect(result).toBeTruthy();
      // do other assertions
      done(); // call done to tell jasmine you're done with the test
    });
  });
})

CodePudding user response:

You have already arranged an ActivatedRouteSnapshot argument and a mock store, all that is left to do is arranging a mock http, then invoking resolve and subscribing to it.

Since your observable behaves in a sync manner, you can safely call expect within callback to make assertions (e.g. given that a is true, b is false and id is 1, observable returned by resolve is expected to emit whatever data you have set for mock http).

  • Related