NGRX单元测试:如何Mock两个不同的Selector
解决MockStore select方法返回多类型数据的问题
你的问题核心在于当前的MockStore不管传入什么selector都固定返回fruit数据,导致组件调用store.select(allAnimals)时拿到的是不符合Animal结构的数据,自然触发filter报错。我们可以让MockStore根据传入的selector动态返回对应结构的模拟数据,完全不需要修改原有业务代码的数据结构。
具体解决方案步骤:
准备对应结构的模拟数据
先在测试文件中定义好和真实Store返回结构一致的模拟数据,确保和两个selector的输出匹配:// 模拟fruitList selector返回的Fruit结构数据 const mockFruitData = { sweet: [], // 可根据测试需求填充具体模拟值 salty: [], bitter: [] }; // 模拟AnimalState结构(对应selectAnimalState返回的类型) const mockAnimalState = { allAnimals: { id: [1, 2, 3], entity: ['monkey', 'elephant', 'snake'] } };修改MockStore的select方法,动态匹配selector
让select方法根据传入的selector判断要返回哪组模拟数据,这里可以用Map来维护selector和数据的映射,方便后续扩展:// 记得导入对应的selector到测试文件中 import { fruitList } from './fruitSelector'; import { allAnimals } from './animalSelector'; class MockStore { // 建立selector与模拟数据的映射关系 private selectorDataMap = new Map([ [fruitList, mockFruitData], [allAnimals, mockAnimalState.allAnimals] ]); public select(selector: any): Observable<any> { // 根据selector获取对应数据,默认返回null避免报错 const targetData = this.selectorDataMap.get(selector) ?? null; return of(targetData); } }保持原有TestBed配置不变
你的beforeEach配置不需要修改,依然使用这个MockStore替代真实Store即可。
为什么这个方案可行?
- 完全隔离了测试环境与生产环境的数据结构,不需要改动任何业务代码
- 通过selector匹配返回对应数据,确保组件中
this.fruit和this.animal拿到的都是符合预期的结构 - 用Map管理映射关系,后续如果需要新增其他selector的模拟数据,只需要在Map中添加新的键值对即可,扩展性强
注意事项
确保模拟数据的结构和真实Store中对应selector返回的结构完全一致,比如allAnimalsselector返回的是status.allAnimals,所以我们的模拟数据要对应返回mockAnimalState.allAnimals,这样组件中的animal.filter()逻辑才能正常执行。
内容的提问来源于stack exchange,提问作者Photonic
相关产品推荐
相关产品推荐

