测试Ngrx Mock Store遇意外错误,Jasmine-Marbles测试问题及解决方案
解决jasmine-marbles测试中"Cannot read property 'pools' of undefined"的问题
看起来你遇到的核心问题是测试里的初始store状态结构不匹配feature selector的预期,导致selector无法正确读取pools属性。让我帮你一步步分析和解决:
错误原因拆解
你看到的错误:
Expected $[0].notification.error = TypeError: Cannot read property 'pools' of undefined to equal undefined.
本质是你的selectPools selector依赖createFeatureSelector('poolManagement')来获取feature级别的state,但测试中设置的初始状态并没有包含poolManagement这个节点:
- 你的selector期望state结构是:
{ poolManagement: { pools: [] } } - 但你在测试里写的
initialState = { pools: [] }是把pools直接放在了根state下,导致poolManagementSelector返回undefined,后续访问state.pools自然就报错了。
修复方案:修正初始状态结构
修改pool-list.component.spec.ts中的初始状态,让它符合feature selector的预期结构:
beforeEach(() => { // 正确的初始状态:包含poolManagement节点 const initialState = { poolManagement: { pools: [] } } as fromPoolManagement.State; TestBed.configureTestingModule({ declarations: [PoolListComponent], providers: [provideMockStore({ initialState })], }).compileComponents(); // 后续代码不变... });
更简洁的测试方式:直接Mock Selector
如果你不想维护整个feature state的结构,可以直接mockselectPools的返回值,这样测试更聚焦于组件逻辑:
beforeEach(() => { TestBed.configureTestingModule({ declarations: [PoolListComponent], providers: [provideMockStore()], // 不需要传入初始状态 }).compileComponents(); fixture = TestBed.createComponent(PoolListComponent); component = fixture.componentInstance; mockStore = TestBed.get(Store); // 直接指定selectPools的返回值 mockStore.overrideSelector(selectPools, []); mockStore.refreshState(); // 刷新状态让组件接收到新值 fixture.detectChanges(); });
额外注意点
fixture.detectChanges()会触发组件的ngOnInit,进而dispatchgetPoolsaction。如果你的reducer/effect会修改pools状态,可能需要在测试前mock这个action的处理,或者确保初始状态不受影响。- 用
jasmine-marbles测试Observable时,确保cold的时间线和实际Observable的发射时机匹配,这里你的测试场景是初始状态,所以cold('a', {a: []})是合理的。
内容的提问来源于stack exchange,提问作者dmance
相关产品推荐
相关产品推荐

