在 Angular 中测试没有插座的路线导航

Testing route navigation without an outlet in Angular

我正在为一个 Angular 组件编写规范,该组件显示一个可以导航到另一个页面的按钮。该组件使用 Router::navigate() 但本身没有路由器插座。父组件有出口。在我的规范中,测试应该确认点击按钮路由到正确的路径。

我当前的(损坏的)规范尝试使用 RouterTestingModule 提供通往 DummyComponent 的路径。在规范中单击按钮时,出现以下错误:

'Unhandled Promise rejection:', 'Cannot find primary outlet to load 'DummyComponent'', '; Zone:', 'angular', '; Task:', 'Promise.then', '; Value:', Error{__zone_symbol__error: Error{originalStack: 'Error: Cannot find primary outlet to load 'DummyComponent'

显然我以错误的方式解决了这个问题。当组件没有路由器插座时,测试路由器导航的正确方法是什么?

组件(伪代码):

@Component({
    template: `
        Go to the <button (click)="nextPage">next page</button>
    `
})
export class ExampleComponent {
    public myId = 5;

    constructor(private _router: Router);

    public nextPage(): void {
        this._router.navigate(['/example', this.myId]);
    }
}

规格。这不起作用:

const FAKE_ID = 999;

describe('ExampleComponent Test', () => {
    let exampleComponent: ExampleComponent;
    let fixture: ComponentFixture<ExampleComponent>;

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [ DummyComponent ],
            imports: [
                RouterTestingModule.withRoutes([
                    { path: 'example/:id', component: DummyComponent }
                ]);
            ]
        });

        fixture = TestBed.createComponent(exampleComponent);
        exampleComponent = fixture.componentInstance;
    });

    it('should route to example/:id', inject([Router, Location], (router: Router, location: Location) => {
        fixture.detectChanges();
        exampleComponent.myId = FAKE_ID;

        const LINK_BUTTON = fixture.debugElement.query(By.css('button'));
        LINK_BUTTON.nativeElement.dispatchEvent(new Event('click'));
        expect(location.path()).toEqual('/example/' + FAKE_ID);
    });
});

DummyComponent 需要一个插座 (<router-outlet>)。如果 DummyComponent 是从 ExampleComponent 导航到的路线,那么 ExampleComponent 应该有出口。您还需要将 ExampleComponent 添加到声明中`

@Component({
  tempalte: `
    <router-outlet></router-outlet>
    <button (click)="nextPage">next page</button>
  `
})
class ExampleComponent{}

declarations: [ ExampleComponent, DummyComponent ]

如果您想避免仅仅为了测试导航到的路由而必须设置此基础结构,更好的选择可能是仅模拟 Router,并检查 navigate使用正确的路径调用方法。

beforeEach(()=>{
  TestBed.configureTestingModule({
    providers: [
      {
        provide: Router,
        useValue: { navigate: jasmine.createSpy('navigate') }
      }
    ]
  })
})

有了这个,您根本不需要配置路由,因为您使用的是假 Router。然后在你的测试中

it('should route to example/:id', inject([Router], (router: Router) => {
  expect(router.navigate).toHaveBeenCalledWith(['/example', FAKE_ID]);
});