如何在jasmine-karma中测试Angular函数if分支内的方法是否被调用
核心思路
你要覆盖代码中的if分支,不需要触发真实路由跳转,只需要模拟Router的events可观察对象,手动抛出NavigationEnd类型的事件,同时验证checkMenuLinks方法是否被正确调用即可。
具体实现步骤
- 在测试用例的TestBed配置中,提供Router的mock实现,将events属性替换为可手动发射值的
Subject对象 - 调用被测的
currentRoute方法完成事件订阅注册 - 手动通过
Subject.next发射一个NavigationEnd实例 - 断言
checkMenuLinks方法是否被传入对应NavigationEnd实例,完成分支覆盖验证
完整测试代码示例
import { TestBed } from '@angular/core/testing'; import { Router, NavigationEnd } from '@angular/router'; import { Subject } from 'rxjs'; // 替换为你自己的组件/服务类路径 import { YourComponent } from './your.component'; describe('YourComponent', () => { let component: YourComponent; let routerEventsSubject: Subject<any>; beforeEach(() => { routerEventsSubject = new Subject<any>(); TestBed.configureTestingModule({ providers: [ YourComponent, { provide: Router, useValue: { events: routerEventsSubject.asObservable() } } ] }); component = TestBed.inject(YourComponent); }); it('should trigger checkMenuLinks when receive NavigationEnd event', () => { // 监听checkMenuLinks调用情况 spyOn(component, 'checkMenuLinks'); // 执行被测方法完成订阅 component.currentRoute(); // 手动发射NavigationEnd事件触发if分支 const mockNavEnd = new NavigationEnd(1, '/test-path', '/test-path'); routerEventsSubject.next(mockNavEnd); // 断言验证分支逻辑执行 expect(component.checkMenuLinks).toHaveBeenCalledOnceWith(mockNavEnd); }); // 可选补充用例:验证非NavigationEnd事件不会触发逻辑 it('should not trigger checkMenuLinks when receive other router event', () => { spyOn(component, 'checkMenuLinks'); component.currentRoute(); // 发射任意非NavigationEnd类型的事件 routerEventsSubject.next({ type: 'NavigationStart' }); expect(component.checkMenuLinks).not.toHaveBeenCalled(); }); });
注意事项
- 必须先调用
currentRoute完成订阅,再发射事件,否则订阅逻辑未注册无法接收到事件 - 该方案使用mock Router替代真实路由模块,测试运行速度更快,也不需要依赖路由配置
内容的提问来源于stack exchange,提问作者Julio Rodríguez
相关产品推荐
相关产品推荐

