Angular+Jest单元测试subscribe方法报错:Cannot spyOn原始值
解决Angular Jest测试中
Cannot spyOn on a primitive value; undefined given报错问题 问题根源
你触发的报错核心原因是:在TestBed配置阶段,mockUserService初始值为undefined,你用useValue: mockUserService注入的是一个无效的原始值,后续尝试对这个undefined对象的getUsers方法做spy操作时,就会抛出该错误。
修复步骤
1. 提前初始化有效的mock服务对象
在测试代码最开始,把mockUserService初始化为包含getUsers方法的模拟对象(或者至少是一个空对象),避免注入undefined。
2. 调整TestBed配置逻辑
确保providers中注入的是已经初始化好的mock对象,而不是未定义的变量。
3. 补全组件依赖的初始化
原方法中用到了this.form?.getRawValue(),如果组件的form未初始化,会导致后续方法调用异常,需要在测试前给form赋值。
完整修复后的测试代码
describe('UserComponent', () => { let component: UserComponent; let fixture: ComponentFixture<UserComponent>; // 提前初始化mock服务,避免undefined let mockUserService: Partial<UserService> = { getUsers: jest.fn() }; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [UserComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA], providers: [ { provide: UserService, useValue: mockUserService }, ], imports: [ HttpClientTestingModule, ReactiveFormsModule, RouterTestingModule, MatDialogModule, BrowserAnimationsModule ] }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(UserComponent); component = fixture.componentInstance; mockUserService = TestBed.inject(UserService); // 初始化组件的form,避免getRawValue()返回undefined component.form = new FormGroup({}); // 如果需要验证agGrid的setRowData,也可以初始化agGrid对象 component.agGrid = { api: { setRowData: jest.fn() } }; }); it('should execute processing methods and call user service when doSearch runs', () => { const mockresponse = { content: [{ businessUnitId: '0800', firstName: 'teste', lastName: 'lastteste', mail: 'teste@gmail.com', isActive: true, }], }; const spysplit = jest.spyOn(component, 'splitStringToGetOnlyTheId'); const spycheck = jest.spyOn(component, 'onCheckEmptyFieldsAndReplaceNull'); const spyService = jest.spyOn(mockUserService, 'getUsers').mockReturnValue(of(mockresponse)); component.doSearch(); expect(spysplit).toHaveBeenCalled(); expect(spycheck).toHaveBeenCalled(); expect(spyService).toHaveBeenCalled(); // 额外验证subscribe内的状态更新逻辑 expect(component.isLoading).toBe(false); expect(component.isShowingTable).toBe(true); expect(component.dataSource).toEqual(mockresponse.content); expect(component.agGrid?.api.setRowData).toHaveBeenCalledWith(mockresponse.content); }); });
额外说明
- 如果你不需要验证
agGrid的方法,可以去掉对应的初始化和断言; - 原
doSearch方法的subscribe没有处理错误分支,如果需要覆盖错误场景,可以给mock的getUsers返回throwError,并验证状态是否正确更新。
内容的提问来源于stack exchange,提问作者unitestangular
相关产品推荐
相关产品推荐

