Angular NX+Jest结构指令测试:不同权限用户断言失败排查
结构指令测试断言失败问题排查与修复
问题背景
使用Nx+Angular+Jest+MockUtils测试结构指令,需验证不同权限用户的视图渲染:admin用户可见4个应用,普通用户可见2个。已模拟AuthService,控制台能输出正确用户角色,指令的ngOnInit也已执行,但断言时component.numApps始终返回0,与预期的2/4不符。
核心问题与修复步骤
1. 测试用例预期值与角色匹配错误
测试用例完全搞反了角色与预期值:
testUser1是admin角色,应预期4个应用,但代码中断言toBe(2)testUser2是普通用户,应预期2个应用,但代码中断言toBe(4)
修正后的测试用例:
test('should display four apps for admin user', async () => { authService.user$.next(testUser1 as any); fixture.detectChanges(); await fixture.whenStable(); expect(component.numApps).toBe(4); }); test('should display two apps for regular user', async () => { authService.user$.next(testUser2 as any); fixture.detectChanges(); await fixture.whenStable(); expect(component.numApps).toBe(2); });
2. AuthService模拟方法的闭包错误
在MockUtils.mockProvider配置中,isAuthorized函数引用了未初始化的外部authService变量(此时authService还未通过TestBed.inject赋值),导致逻辑异常。应改用this访问mock实例的user$:
MockUtils.mockProvider(AuthService, { user$: new BehaviorSubject<any | null>(null), isAuthorized: jest.fn((someFlag: string) => { const user = this.user$.value as any; // 改用this访问mock实例的user$ console.log(`USER: ${user.role}`); return user.role === 'admin'; }) })
3. 异步订阅的时机问题
指令中订阅user$是异步操作,同步执行的fixture.detectChanges()可能导致断言时回调未执行。需用fixture.whenStable()等待异步任务完成后再断言(如上述修正后的测试用例所示)。
4. 确认宿主组件统计逻辑正确性
确保TestHostComponent的numApps正确统计指令渲染的实例数量,示例实现:
@Component({ template: ` <div *myStructuralDirective>App 1</div> <div *myStructuralDirective>App 2</div> <div *myStructuralDirective>App 3</div> <div *myStructuralDirective>App 4</div> ` }) class TestHostComponent { @ViewChildren(MyStructuralDirective) apps!: QueryList<MyStructuralDirective>; get numApps() { return this.apps?.length || 0; } }
5. 调整变更检测触发时机
在user$.next后,可连续触发两次变更检测:第一次触发指令初始化执行订阅,第二次确保视图更新完成:
test('should display two apps for regular user', async () => { authService.user$.next(testUser2 as any); fixture.detectChanges(); // 触发指令ngOnInit fixture.detectChanges(); // 触发视图渲染更新 await fixture.whenStable(); expect(component.numApps).toBe(2); });
内容的提问来源于stack exchange,提问作者fumeng
相关产品推荐
相关产品推荐

