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

Angular 5使用@ngrx/router-store测试组件遇Karma错误求助

解决NgRx Router Store测试中的state未定义与beforePreactivation错误

我来帮你拆解一下这个问题,你遇到的其实是NgRx Router Store在测试环境中常见的依赖配置问题,咱们一步一步来解决:

1. 核心问题分析

你一开始碰到的state.router未定义,本质是测试模块没有正确初始化NgRx Router Store的状态,导致选择器拿不到路由相关的state;而添加StoreRouterConnectingModule.forRoot()后出现的Cannot set property 'beforePreactivation' of undefined,则是因为测试环境里Angular Router的核心钩子依赖缺失——Router Store需要依赖Router实例的hooks对象,但测试模块中的Router可能没完成正确初始化。

2. 测试场景的正确配置方案

在测试NgRx Router Store相关组件时,不建议直接用StoreRouterConnectingModule.forRoot(),更稳妥的方式是用模拟状态或者补全Router依赖,以下两种方案任选:

方案一:手动模拟Router State(最简单直接)

不需要导入StoreRouterConnectingModule,而是在StoreModule.forRoot中给router reducer提供初始模拟状态,让选择器能拿到有效数据:

import * as fromRouter from '@ngrx/router-store';

// 模拟Router的初始状态
const mockRouterState: fromRouter.RouterReducerState<RouterStateUrl> = {
  state: {
    url: '/test-wizard',
    queryParams: {},
    params: {}
  },
  navigationId: 1
};

// 合并你的其他reducers
const reducers = {
  // 你的业务reducers...
  router: fromRouter.routerReducer
};

// 配置TestBed
TestBed.configureTestingModule({
  imports: [
    RouterModule.forRoot([]), // 必须导入RouterModule,至少配置空路由
    StoreModule.forRoot(reducers, {
      initialState: {
        router: mockRouterState // 手动注入router初始状态
      },
      metaReducers
    }),
    EffectsModule.forRoot([MyEffects, WizardEffects]),
    HttpClientModule
  ],
  // 其他配置:declarations、providers等
});

方案二:补全Router依赖适配StoreRouterConnectingModule

如果你需要更贴近真实环境的测试,想保留StoreRouterConnectingModule.forRoot(),可以手动初始化Router的hooks对象,解决beforePreactivation未定义的问题:

import { Router } from '@angular/router';
import { StoreRouterConnectingModule } from '@ngrx/router-store';

beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [
      RouterModule.forRoot(wizardRoutes),
      StoreModule.forRoot(reducers, { metaReducers }),
      EffectsModule.forRoot([MyEffects, WizardEffects]),
      HttpClientModule,
      StoreRouterConnectingModule.forRoot()
    ]
  });

  // 获取Router实例,手动初始化hooks对象
  const router = TestBed.inject(Router);
  router.hooks = router.hooks || {}; // 确保hooks存在,避免undefined报错
});

3. 额外优化建议

  • 确保你的AppState接口正确包含router: fromRouter.RouterReducerState<RouterStateUrl>,避免类型不匹配的隐性问题;
  • 测试环境下优先用RouterTestingModule替代RouterModule,它是Angular专门为测试优化的路由模块,能减少很多依赖问题:
import { RouterTestingModule } from '@angular/router/testing';

// 替换原有的RouterModule配置
TestBed.configureTestingModule({
  imports: [
    RouterTestingModule.withRoutes(wizardRoutes),
    // 其他导入...
  ]
});

按照上面的配置调整后,你的选择器应该能正常获取router state,同时Karma浏览器中的错误也会消失。

内容的提问来源于stack exchange,提问作者serlingpa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:13:41