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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 04:18:14