Angular中用Karma+Jasmine单元测试如何验证父方法调用后嵌套方法执行
问题原因
- 仅执行
currentRoute()只会完成router.events的订阅注册,测试环境不会自动触发NavigationEnd类型的路由事件,订阅内的回调逻辑全程没有执行,自然不会调用getLaneMakersData。 - 断言语法错误,Jasmine的
toHaveBeenCalled是可执行方法,需要添加括号调用,缺少括号会导致断言逻辑错误。 - 未提前Mock依赖项返回值:需要保证
userService.userPermissions.hasLaneMakersLookupPermission为true,且component.searchResults已正确赋值为'/sl/(mobileOutlet:search-results)',否则即使触发路由事件,判断条件也不会满足。
修复方案
步骤1:在测试模块中Mock依赖项
用RxJS的Subject模拟Router的events流,同时Mock UserService确保权限返回正确值:
import { Subject } from 'rxjs'; import { NavigationEnd, Router } from '@angular/router'; // 替换为你实际的UserService导入路径 import { UserService } from './user.service'; // 测试模块配置 const mockRouterEvents = new Subject(); TestBed.configureTestingModule({ // 其他配置省略 providers: [ { provide: Router, useValue: { events: mockRouterEvents.asObservable() } }, { provide: UserService, useValue: { userPermissions: { hasLaneMakersLookupPermission: true } } } ] })
步骤2:修正测试用例写法
手动触发符合要求的NavigationEnd事件,修正断言语法:
describe('currentRoute', () => { it('calls the getLaneMakersData method and assigns values correctly', () => { // 提前赋值searchResults component.searchResults = '/sl/(mobileOutlet:search-results)'; spyOn(component, 'getLaneMakersData'); // 注册路由事件订阅 component.currentRoute(); // 手动发射符合条件的NavigationEnd事件 const testNavEnd = new NavigationEnd( 1, '/sl/(mobileOutlet:search-results)', '/sl/(mobileOutlet:search-results)' ); mockRouterEvents.next(testNavEnd); // 断言所有逻辑符合预期 expect(component.displayLaneMakersLink).toBeTrue(); expect(component.laneMakerLinkVisible).toBeTrue(); expect(component.getLaneMakersData).toHaveBeenCalled(); }); });
额外优化建议
原业务代码中的router.events订阅没有取消逻辑,会存在内存泄漏风险,建议添加takeUntil(this.destroy$)之类的取消订阅逻辑,在组件销毁时自动结束订阅。
内容的提问来源于stack exchange,提问作者Julio Rodríguez
相关产品推荐
相关产品推荐

