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
相关产品推荐
相关产品推荐

