Angular 16迁移Signals后,NgRx MockStore overrideSelector单元测试异常求助
解决方案:在it块中使用MockStore.overrideSelector适配Angular Signals
问题根源
你组件里用store.selectSignal()创建的信号,会在组件初始化时就绑定对应的selector值。但MockStore的overrideSelector原本是给Observable设计的,在it块里调用时,不会自动触发Signals的变更通知,导致组件里的信号拿不到新值。
可行解决办法
办法1:调用refreshState()手动触发更新
在it块里改完selector值后,手动调用mockStore.refreshState(),强制通知所有基于store的信号更新:
it('should display updated username from it block', () => { mockStore.overrideSelector(selectUsername, 'Jane Doe'); // 手动刷新状态,触发信号更新 mockStore.refreshState(); fixture.detectChanges(); expect(usernameElement.textContent).toContain('Jane Doe'); });
办法2:直接用setState()更新全局状态
如果不需要单独覆盖某个selector,也可以直接设置整个mock状态,同样要配合refreshState():
it('should display updated username from it block', () => { mockStore.setState({ user: { username: 'Jane Doe' } }); mockStore.refreshState(); fixture.detectChanges(); expect(usernameElement.textContent).toContain('Jane Doe'); });
办法3:用computed包裹衍生信号(可选优化)
如果组件里的信号是基于selector信号的衍生值,用computed()包裹它,确保能自动响应selector的变更:
// 组件内部代码 username = computed(() => this.store.selectSignal(selectUsername)());
补充说明
你注释掉的那行代码(直接赋值username = this.store.selectSignal(selectUsername)())之所以能过测试,是因为它只在初始化时取一次值,后续selector变更不会影响它——但这违背了Signals的响应式设计,不能作为长期方案。而refreshState()是NgRx 16+专门为Signals新增的方法,用来弥补overrideSelector在Signals场景下的通知缺失。
内容的提问来源于stack exchange,提问作者Shining
相关产品推荐
相关产品推荐

