Все примеры, которые я могу найти, показывают только то, как тестировать компонент, который вызывает navigateByUrl. У меня есть служба, которая это делает:
@Injectable({
providedIn: 'root'
})
export class BreadcrumbService {
constructor(private router: Router, private activateRoute: ActivatedRoute) {}
/**
* Return a array of current path
*
*/
getCurrentRouterPath(): Array<string> {
return this.router.url.split('/').filter(path => path);
}
}
Я пытаюсь проверить это, издевавшись над маршрутизатором:
import {TestBed, async, inject} from '@angular/core/testing';
import {BreadcrumbService} from './breadcrumb.service';
import {ActivatedRoute, Router} from '@angular/router';
class MockRouter {
navigateByUrl(url: string) {
return { url };
}
}
describe('BreadcrumbService', () => {
let service: BreadcrumbService;
let activateRoute: ActivatedRoute;
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
{ provide: Router, useClass: MockRouter },
{ provide: ActivatedRoute }
]
});
activateRoute = TestBed.inject(ActivatedRoute);
service = TestBed.inject(BreadcrumbService);
}));
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should return an array of route path', inject([Router], (router: MockRouter) => {
const spy = spyOn(router, 'navigateByUrl');
router.navigateByUrl('/giveaway/all');
const arrayPath = service.getCurrentRouterPath();
expect(arrayPath).not.toBeNull();
expect(arrayPath).not.toBeUndefined();
expect(arrayPath).toEqual(['giveaway', 'all']);
}));
});
... но URL-адрес всегда не определен, поэтому cannot read property 'split of undefined occurs.
Что я пробовал
Поэтому я решил имитировать само свойство url, чтобы избежать этого:
class MockRouter {
private _url = '';
get url(): string {
return this._url;
}
set url(value: string) {
this._url = value;
}
}
Теперь тест выполняется, но свойство url всегда пусто, поэтому я возвращаю пустой массив, поэтому тест не проходит.
Хорошо, поэтому я могу выполнить этот проход, явно установив URL-адрес непосредственно в макете, но мне это кажется неправильным так как он полностью пропускает этап навигации (как вы заметили, я удалил navigateByUrl
из имитируемого класса):
it('should return an array of route path', inject([Router], (router: MockRouter) => {
router.url = '/giveaway/all';
const arrayPath = service.getCurrentRouterPath();
expect(arrayPath).not.toBeNull();
expect(arrayPath).not.toBeUndefined();
expect(arrayPath).toEqual(['giveaway', 'all']);
}));
Итак, здесь действительно есть 3 вопроса:
-
НЕ должен ли я издеваться над маршрутизатором, а фактически вводить настоящий маршрутизатор и фактически запускать событие навигации в тесте? (пробовал это, ничего не получается! - см. примечание ниже)
Имеет ли значение (1), если я просто go с тем, что работает выше, поскольку он действительно тестирует метод в service?
Нужно ли мне вообще тестировать этот метод, поскольку все, от чего он действительно зависит, - это другие вещи, которые уже проверены другими разработчиками (ie маршрутизатор Angular, массив разделить и отфильтровать).
ПРИМЕЧАНИЕ
Я унаследовал код, и изначально он был таким, как показано ниже, где тест никогда не терпит неудачу:
import {TestBed} from '@angular/core/testing';
import {BreadcrumbService} from './breadcrumb.service';
import {RouterTestingModule} from '@angular/router/testing';
import {ActivatedRoute, Router} from '@angular/router';
import {NgZone} from '@angular/core';
describe('BreadcrumbService', () => {
let service: BreadcrumbService;
let router: Router;
let activateRoute: ActivatedRoute;
let ngZone: NgZone;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([])]
});
router = TestBed.inject(Router);
activateRoute = TestBed.inject(ActivatedRoute);
service = TestBed.inject(BreadcrumbService);
ngZone = TestBed.inject(NgZone);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should receive a array of route path', () => {
ngZone.run(() => {
router.navigateByUrl('/giveaway/all').then(() => {
const arrayPath = service.getCurrentRouterPath();
expect(arrayPath).not.toBeNull();
expect(arrayPath).not.toBeUndefined();
expect(arrayPath.length).toEqual(2);
});
});
});
});
который всегда проходит независимо от длины вызываемой вами навигации или проверки равенства. Таким образом, даже это проходит:
expect(arrayPath.length).toEqual(200)
и это:
expect(arrayPath.length).toEqual(0)
, что кажется очень странным.
Если кто-нибудь может объяснить, почему используется настоящий маршрутизатор и навигация не вышло Буду безмерно признателен!