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

Angular 18 + Jest 29:如何在单元测试中动态修改ActivatedRoute快照的permissions数组值

Angular 18 + Jest 29:如何在单元测试中动态修改ActivatedRoute快照的permissions数组值

我来帮你拆解问题根源,再给出可落地的解决方案!

问题到底出在哪?

你当前的测试逻辑有两个核心问题,导致修改permissions始终不生效:

  1. ngOnInit执行时机过早:在beforeEach里你调用了fixture.detectChanges(),这会立刻触发组件的ngOnInit方法。此时route.snapshot.data.session.permissions还是初始的空数组,之后在测试用例里修改route的值,已经晚了——ngOnInit已经执行完毕,不会重新读取新的权限值。
  2. 共享路由实例的状态污染:你在describe作用域创建了单个MockActivatedRoute实例,所有测试用例共享它。如果没有正确重置状态,后续测试会继承之前的修改,导致逻辑混乱。

解决方案:调整执行顺序 + 手动触发初始化

我们需要把ngOnInit的触发时机推迟到每个测试用例中,先设置好想要的权限值,再让组件读取并执行逻辑。

步骤1:修改beforeEach,移除提前触发的detectChanges

首先,在beforeEach里不要调用fixture.detectChanges(),避免过早执行ngOnInit:

beforeEach(async () => {
  await TestBed.configureTestingModule({
    imports: [],
    providers:[
      provideHttpClient(),
      provideHttpClientTesting(),
      { provide: ActivatedRoute, useValue: route},
    ],
    declarations: [ SidebarComponent ],
    schemas: [NO_ERRORS_SCHEMA],
  }).compileComponents();

  fixture = TestBed.createComponent(SidebarComponent);
  component = fixture.componentInstance;
  // 移除这行:fixture.detectChanges();
});

步骤2:在每个测试用例中先设置权限,再触发ngOnInit

现在你可以在每个测试里自由修改权限,然后手动触发组件初始化逻辑:

// 测试无权限的场景(原通过的测试调整后)
it('should not call getRequestSummary when Permissions.VIEW_REQUEST_SUMMARY_PERMISSION does not exist', () => {
  // 确保权限数组为空
  route.snapshot.data.session.permissions = [];
  // 手动触发ngOnInit,让组件读取最新权限
  component.ngOnInit();
  // 验证方法未被调用
  const spy = jest.spyOn(mockAccountsService, 'getRequests');
  expect(spy).not.toHaveBeenCalled();
});

// 测试有权限的场景
it('should call getRequestSummary when Permissions.VIEW_REQUEST_SUMMARY_PERMISSION does exist', () => {
  // 设置目标权限
  route.snapshot.data.session.permissions = [Permissions.VIEW_REQUEST_SUMMARY_PERMISSION];
  // 手动触发ngOnInit
  component.ngOnInit();
  // 验证方法被调用
  const spy = jest.spyOn(mockAccountsService, 'getRequests');
  expect(spy).toHaveBeenCalled();
});

可选优化:每个测试用例使用独立的路由实例

如果你想彻底避免测试之间的状态污染,可以在beforeEach里每次创建新的MockActivatedRoute实例:

describe('SidebarComponent', () => {
  let component: SidebarComponent;
  let fixture: ComponentFixture<SidebarComponent>;
  let route: MockActivatedRoute; // 只声明,不提前实例化

  beforeEach(async () => {
    // 每次创建新的路由实例
    route = new MockActivatedRoute();
    route.snapshot = {
      data: { session: { permissions: [] } },
    };

    await TestBed.configureTestingModule({
      // ... 其他配置不变
      providers:[
        provideHttpClient(),
        provideHttpClientTesting(),
        { provide: ActivatedRoute, useValue: route}, // 使用新创建的route
      ],
    }).compileComponents();

    fixture = TestBed.createComponent(SidebarComponent);
    component = fixture.componentInstance;
  });

  // 测试用例和上面一致
});

为什么之前的尝试没生效?

  • 你用jest.spyOn或jest.replaceProperty修改权限时,ngOnInit已经执行过了,组件不会重新读取新的权限值。
  • fixture.detectChanges()在beforeEach里的调用时机太早,直接固化了初始权限的逻辑判断结果。

这样调整后,你就能在不同测试用例中灵活切换permissions数组的值,准确验证组件的逻辑了!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 14:33:00