You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何对navigateByUrl间谍对象的expect断言需使用正则匹配器?

Angular Router测试中navigateByUrl间谍断言不一致问题解析

问题现象

对Angular Router的navigateByUrl方法创建间谍后,两种断言方式出现明显不一致:

可正常运行的代码

const routerSpy = spyOn(TestBed.inject(Router), 'navigateByUrl');
const thing = fixture.debugElement.query(By.css('.list .list-group-item'));
expect(thing).not.toBeNull();

thing.triggerEventHandler('click', new Event('click'));

expect(routerSpy).toHaveBeenCalledOnceWith(jasmine.stringMatching(/\/thing\/1/), jasmine.any(Object));

断言失败的代码

...
expect(routerSpy).toHaveBeenCalledOnceWith('/thing/1', jasmine.any(Object));

后者触发的错误信息:

Expected $[0] = /thing/1 to equal '/thing/1'.

触发点击的元素为:

<a [routerLink]="['./thing', thing.id]" ...>

核心原因

问题根源在于Angular Router对routerLink的处理逻辑:

  • 当绑定[routerLink]="['./thing', thing.id]"这种数组形式的相对路径时,Angular会基于当前激活路由,将其解析为UrlTree对象——这是Router内部用来描述路由状态的结构化对象,而非原始字符串。
  • 使用jasmine.stringMatching断言时,Jasmine会自动调用UrlTree的toString()方法,将其转换为对应的路径字符串(如/thing/1),再用正则匹配,因此能成功匹配。
  • 直接用字符串'/thing/1'断言时,Jasmine会执行严格相等性检查:实际传入的UrlTree对象和字符串类型完全不同,自然匹配失败。错误信息里的/thing/1只是UrlTree对象toString()后的展示值,并非实际传入的字符串参数。

可选解决方法

  1. 继续使用正则匹配:这是最简便的方式,直接用jasmine.stringMatching匹配UrlTree转换后的字符串。
  2. 序列化UrlTree后断言:利用Router的serializeUrl方法将UrlTree转为字符串再匹配:
    const router = TestBed.inject(Router);
    // 先确认调用参数是UrlTree,再匹配其字符串形式
    expect(routerSpy).toHaveBeenCalledOnceWith(jasmine.any(UrlTree), jasmine.any(Object));
    expect(router.serializeUrl(routerSpy.calls.first().args[0])).toMatch(/\/thing\/1/);
    
  3. 构建预期UrlTree断言:提前创建与routerLink解析结果一致的UrlTree对象:
    const router = TestBed.inject(Router);
    const activatedRoute = TestBed.inject(ActivatedRoute);
    const expectedUrlTree = router.createUrlTree(['./thing', 1], { relativeTo: activatedRoute });
    expect(routerSpy).toHaveBeenCalledOnceWith(expectedUrlTree, jasmine.any(Object));
    

内容的提问来源于stack exchange,提问作者Derek White

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 17:54:54