Jasmine Karma单元测试中如何mock BuilderComponent的builderStore
NgRx单元测试Store.select返回undefined解决方法
核心错误原因
- 你在测试用例中手动创建的
jasmine.createSpyObj生成的store实例,没有注入到组件中,组件实际使用的依然是TestBed初始化时生成的MockStore实例,你对自建spy的修改完全不会生效 provideMockStore传入的initialState是根状态的完整结构,你需要selectbuilder切片,就必须保证根状态下存在builder字段,你直接把IBuilder类型的状态作为根状态传入,自然无法通过select('builder')拿到值fixture.detectChanges()执行时已经触发了一次ngOnInit,后续你手动调用component.ngOnInit()属于重复执行,且此时你还没有修改store的返回值,自然拿到的是undefined
修改后的测试代码
第一步:调整导入和变量定义
// 导入MockStore类型 import { MockStore, provideMockStore } from '@ngrx/store/testing'; describe('BuilderComponent', () => { let component: BuilderComponent; let initialState: IBuilder; let fixture: ComponentFixture<BuilderComponent>; // 新增mockStore变量 let mockStore: MockStore; const state = TEST_BUILDER_INITIAL_STATE;
第二步:修改TestBed的provideMockStore配置
providers: [ // 调整initialState结构,根状态新增builder字段对应切片状态 provideMockStore({ initialState: { builder: state } }), BuilderService, ToastrService, BsModalRef, UserService, QuillService, ]
第三步:调整beforeEach逻辑
beforeEach(() => { fixture = TestBed.createComponent(BuilderComponent); component = fixture.componentInstance; // 获取TestBed中注入的MockStore实例 mockStore = TestBed.inject(MockStore); // detectChanges放在store准备完成后执行,自动触发ngOnInit fixture.detectChanges(); });
第四步:简化测试用例
describe('ngOnInit()', () => { it('should retrieve values from store', () => { // 不需要自建spy、不需要手动调用ngOnInit // 如果需要临时修改返回值可执行以下两行代码: // mockStore.overrideSelector('builder', 自定义测试状态); // mockStore.refreshState(); expect(component['courseBuffer']).toBeDefined(); expect(component['courseName']).toBeDefined(); expect(component['selectedCourseContentElementUid']).toBeUndefined(); }); });
补充注意事项
如果你的项目根状态还有其他切片(比如auth、user对应的状态),需要在provideMockStore的initialState中一并补充对应字段,避免其他Store的select调用报错。
内容的提问来源于stack exchange,提问作者methuselah
相关产品推荐
相关产品推荐

