Weboldal keresés

typescript - Angular 6 - hogyan kell a router.events URL válaszát mockolni egységtesztben


Ahogy a cím is mutatja, egységtesztben kell megtévesztenem a router.events-et.

Az én komponensemben csinálok némi reguláris kifejezést, hogy megragadjam az első szövegrészletet a slash-ek között az URL-ben; pl. /pdp/

  constructor(
    private route: ActivatedRoute,
    private router: Router,
  }

this.router.events.pipe(takeUntil(this.ngUnsubscribe$))
      .subscribe(route => {
        if (route instanceof NavigationEnd) {
        // debugger
          this.projectType = route.url.match(/[a-z-]+/)[0];
        }
      });

Az egységtesztjeim hibát jeleznek, amikor az összetevőt építik: Cannot read property '0' of null. Amikor bekapcsolom a hibakeresőt, route úgy tűnik, nem megfelelően van beállítva, pedig az egységtesztben magában állítom be. Többféleképpen is próbáltam (inspirálva ettől a bejegyzéstől: Mocking router.events.subscribe() Angular2 és mások).

Első próbálkozás:

providers: [
        {
          provide: Router,
          useValue: {
            events: of(new NavigationEnd(0, '/pdp/project-details/4/edit', 'pdp/project-details/4/edit'))
          }
        },
        // ActivatedRoute also being mocked
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: { url: [{ path: 'new' }, { path: 'edit' }] },
            parent: {
              parent: {
                snapshot: {
                  url: [
                    { path: 'pdp' }
                  ]
                }
              }
            }
          }
        }
]

Második próbálkozás (a fenti bejegyzés alapján):

class MockRouter {
  public events = of(new NavigationEnd(0, '/pdp/project-details/4/edit', '/pdp/project-details/4/edit'))
}

providers: [
        {
          provide: Router,
          useClass: MockRouter
        }
]

Harmadik próbálkozás (szintén a fenti bejegyzés alapján):

class MockRouter {
  public ne = new NavigationEnd(0, '/pdp/project-details/4/edit', '/pdp/project-details/4/edit');
  public events = new Observable(observer => {
    observer.next(this.ne);
    observer.complete();
  });
}

providers: [
        {
          provide: Router,
          useClass: MockRouter
        }
]

Negyedik próbálkozás:

beforeEach(() => {
    spyOn((<any>component).router, 'events').and.returnValue(of(new NavigationEnd(0, '/pdp/project-details/4/edit', 'pdp/project-details/4/edit')))
...

Ötödik kísérlet:

beforeEach(() => {
    spyOn(TestBed.get(Router), 'events').and.returnValue(of({ url:'/pdp/project-details/4/edit' }))
...

A fentiek mindegyikében a route nincs beállítva; a NavigationEnd objektum egyenlő a következővel:

{ id: 1, url: "/", urlAfterRedirects: "/" }

Gondolatok?

Válasz #1

Olyan egyszerű is lehet, mint:

TestBed.configureTestingModule({
  imports: [RouterTestingModule]
}).compileComponents()
    
...
    
const event = new NavigationEnd(42, '/', '/');
(TestBed.inject(Router).events as Subject<Event>).next(event);

Válasz #2

Itt van a válasz, amire rájöttem. Azt hiszem, egyszerűen nem terjesztettem ki eléggé az első megközelítést (fent):

import { of } from 'rxjs';
import { NavigationEnd, Router } from '@angular/router';

providers: [
    {
      provide: Router,
      useValue: {
        url: '/non-pdp/phases/8',
        events: of(new NavigationEnd(0, 'http://localhost:4200/#/non-pdp/phases/8', 'http://localhost:4200/#/non-pdp/phases/8')),
        navigate: jasmine.createSpy('navigate')
      }
    }
]

Kapcsolódó cikkek