我想测试组件如何在我的测试中处理this.activatedRoute.paramMap
,不模拟ActivatedRoute(即使用RouterTestingModule,没有 spy 或模拟)。
如下stackblitz ,我设置了一个相当简单的组件来监听 id
路由参数:
@Component({ /* ... */})
export class RoutingExamplesComponent {
constructor(private readonly route: ActivatedRoute, /* ... */) {}
readonly param$ = this.route.paramMap.pipe(map(params => params.get('id') ?? '<none>'));
// ...
}
在我的测试中,我想设置我的路线并确保参数传播良好:
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
RoutingExamplesModule,
RouterTestingModule.withRoutes([
{
path: "route/:id",
component: RoutingExamplesComponent
}
])
]
});
fixture = TestBed.createComponent(RoutingExamplesComponent);
component = fixture.componentInstance;
router = TestBed.get(Router);
});
it("receives initial setup", async () => {
fixture.detectChanges();
await router.navigate(["route", "1234"]);
fixture.detectChanges();
expect(fixture.nativeElement.querySelector("p").textContent).toContain(
"1234"
);
});
此测试未通过,因为看起来参数未传播:
Expected '<none>' to contain '1234'.
Error: Expected '<none>' to contain '1234'. at <Jasmine> at UserContext.eval (https://angular-routing-playground-routing-test.stackblitz.io/~/app/routing-examples/routing-examples.component.spec.ts:31:80)
如何在不以任何方式模拟路由器的情况下获得正确的参数?
关于我正在做的事情的一些可选上下文:大多数有关路由器测试的堆栈溢出响应都建议模拟它,我认为这是一个严重的错误。一般来说,我已经成功地针对 RouterTestingModule 进行了测试,但是 paramMap 与子路由器相关。
最佳答案
因此,经过大量调查后,我实际上找到了两种解决此问题的方法。
未提供路由参数,因为路由器的上下文与嵌入 <router-outlet>
的组件中的上下文相同。 。由于我们不在路由器导出内,因此没有绑定(bind)到导出的路由,因此我们没有传播路由参数。
解决方案 1:让其如同在路由器 socket 中
这个解决方案基本上覆盖了 ActivatedRoute
提供者提供路由器的第一个 child 。这使用与其定义相同的注入(inject)机制,但提供根上下文的第一个子级而不是根上下文:
TestBed.configureTestingModule({
imports: [
RoutingExamplesModule,
RouterTestingModule.withRoutes([
// ...
])
],
providers: [
// Patches the activated route to make it as if we were in the
// <router-outlet>, so we can access the route parameters.
{
provide: ActivatedRoute,
useFactory: (router: Router) => router.routerState.root.firstChild,
deps: [Router],
}
],
});
权衡:这意味着导航需要在组件实例化之前触发,否则您将无法定义路由的第一个子级:
beforeEach(async () => {
TestBed.configureTestingModule( ... );
router = TestBed.get(Router);
await router.navigate(["route", "1234"]);
fixture = TestBed.createComponent(RoutingExamplesComponent);
});
解决方案 2:在路由器 socket 中引导组件
这基本上意味着您实例化一个简单的组件,只需渲染 <router-outlet></router-outlet>
然后您创建这个组件。
权衡:您不再能够直接访问固定装置,您需要检索调试组件。
关于angular - 测试ActivatedRoute.paramMap而不模拟路由器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65902273/