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

Angular单元测试报错:期望Router.navigate被调用但未触发

Angular Router Spy测试失败问题解决

问题说明

调用组件的changeCompNumber方法时,内部会触发Router.navigate,但单元测试中断言该方法的spy被调用时失败,错误提示:

Expected spy navigate to have been called.

组件代码

@Component({
    selector: "app-comp",
    standalone: true,
    imports: [],
    templateUrl: "./comp.component.html",
    styleUrl: "./comp.component.scss"
})
export class CompComponent implements OnInit {

    constructor(public router: Router, public route: ActivatedRoute) {}

    changeCompNumber(newCompNumber: number) {
        this.router.navigate([], { queryParams: { 'comp': newCompNumber }, queryParamsHandling: 'merge'});
    }

}

原测试代码

describe('CompComponent', () => {
    let component: CompComponent;
    let fixture: ComponentFixture<CompComponent>;
    let ngZone: NgZone;
    let router: Router;

    beforeEach(async () => {
        await TestBed.configureTestingModule({
            imports: [RouterTestingModule, CompComponent]
        }).compileComponents();

        fixture = TestBed.createComponent(CompComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
        ngZone = TestBed.inject(NgZone);
        router = TestBed.inject(Router);
    });

   it("should change comp number", fakeAsync(() => {

        ngZone.run(() => {
            component.changeCompNumber(20);
            tick()
            fixture.detectChanges();
        });
        const navSpy = spyOn(router, "navigate");
        expect(navSpy).toHaveBeenCalled();
    }))
});

错误原因

核心问题是spy创建时机错误:你先执行了changeCompNumber方法(此时router.navigate已经调用),之后才创建navSpy,导致spy完全没捕获到这次调用。另外ngZone.run是多余的,RouterTestingModule已经处理了路由的Zone上下文问题。

修复方案

调整spy创建顺序,先创建spy再执行组件方法,同时简化多余的Zone包裹:

it("should change comp number", fakeAsync(() => {
    // 1. 先创建Router.navigate的spy
    const navSpy = spyOn(router, "navigate").and.callThrough();

    // 2. 执行组件方法
    component.changeCompNumber(20);
    tick();
    fixture.detectChanges();

    // 3. 断言spy被调用
    expect(navSpy).toHaveBeenCalled();
    // 可选:进一步断言调用参数是否符合预期
    expect(navSpy).toHaveBeenCalledWith([], {
        queryParams: { 'comp': 20 },
        queryParamsHandling: 'merge'
    });
}))

额外提示

  • 如果不需要实际执行路由导航,可将and.callThrough()换成and.stub(),避免测试中触发真实路由行为
  • 组件代码中changeCompNumber方法末尾缺少分号,建议补上避免语法问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 00:42:33