angular - 在不模拟路由器的情况下测试 ActivatedRoute.paramMap
问题描述
我想测试一个组件this.activatedRoute.paramMap
在我的测试中是如何处理的,而不模拟ActivatedRoute(即使用RouterTestingModule,没有间谍或模拟)。
在下面的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>
. 由于我们不在路由器出口内,我们没有绑定到出口的路由,因此我们没有传播路由参数。
解决方案 1:让它就像在路由器插座中一样
该解决方案基本上覆盖ActivatedRoute
提供者以提供路由器的第一个子节点。这使用与其定义相同的注入机制,但提供了根上下文的第一个孩子而不是根上下文:
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:在路由器插座中引导组件
这基本上意味着您实例化一个简单的组件,只需渲染<router-outlet></router-outlet>
并创建这个组件。
权衡:您不再可以访问开箱即用的夹具,您需要检索调试组件。
推荐阅读
- java - 当 HasMap 增加它的大小时,它的值的索引会发生什么?
- javascript - 使用node js从mongodb下载大量数据
- exception - RxJava2 Flowable onErrorReturn 未调用
- python - 如何使用python对复杂列表进行排序?
- python - 如何从字典中仅提取某些值(python)
- python - 如何在 pex 文件中使用 ubuntu 包
- javascript - 将 JSON 转换为 ANY 类型的 TW 对象
- angular - 社交登录 - 权限
- firebase - 在 Unity 中集成 Firebase 后无法在 Android 设备上运行
- python - 在 pandas 数据框中使用 bin