Angular单元测试:Mock服务方法未生效无法读取属性报错
问题根因
- Spy打桩时机晚于初始化逻辑执行
你在第一个beforeEach中完成组件创建后立即执行了fixture.detectChanges(),Angular首次执行该方法时会自动触发组件的ngOnInit生命周期,此时fetchWeights方法已经运行。但你对weighInsService的Spy配置写在it测试用例内部,初始化执行时打桩逻辑还未生效,方法调用返回undefined,读取属性直接报错。 - 缺失
findLastWithField方法的打桩配置
组件fetchWeights方法同时调用了findFirstWithField和findLastWithField两个方法,你只配置了前者的返回值,后者未打桩时默认返回undefined,读取current_weight属性也会触发相同报错。 - TestBed配置缺失必要依赖
组件构造函数注入了ModalController、CheckInsProvider,但测试模块的providers列表中没有提供这两个依赖,即便修复当前报错,后续也会触发注入失败问题。
修正后的测试代码
describe('ReEvaluationComponent', () => { let component: ReEvaluationComponent; let fixture: ComponentFixture<ReEvaluationComponent>; let mockGlobalsService = jasmine.createSpyObj('GlobalsService', ['base_url']) // 提前创建mock依赖 let mockModalCtrl = jasmine.createSpyObj('ModalController', ['dismiss']) let mockCheckInsProvider = jasmine.createSpyObj('CheckInsProvider', [/* 填入组件用到的对应方法名 */]) let mockWeighInsProvider = jasmine.createSpyObj('WeighInsProvider', ['findFirstWithField', 'findLastWithField']) let injector: TestBed; let weighInsService: any; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ ReEvaluationComponent ], imports: [ IonicModule.forRoot(), HttpClientTestingModule, RouterTestingModule, ], providers: [ // 替换为mock依赖,避免真实服务的额外依赖影响测试 {provide: WeighInsProvider, useValue: mockWeighInsProvider}, {provide: ModalController, useValue: mockModalCtrl}, {provide: CheckInsProvider, useValue: mockCheckInsProvider}, {provide: GlobalsService, useValue: mockGlobalsService}, {provide: PurchasesService, useValue: PurchasesServiceMock}, ] }).compileComponents(); fixture = TestBed.createComponent(ReEvaluationComponent); component = fixture.componentInstance; // 删掉此处的detectChanges,放到it用例中打桩完成后再执行 })); beforeEach(() => { injector = getTestBed() weighInsService = injector.get(WeighInsProvider) }) it('should create', () => { // 先给两个调用的方法都配置返回值 weighInsService.findFirstWithField.and.returnValue({ current_weight: 200, visceral_fat: 20, body_fat: 20 }) weighInsService.findLastWithField.and.returnValue({ current_weight: 180, visceral_fat: 15, body_fat: 18 }) // 打桩完成后再触发组件初始化 fixture.detectChanges(); expect(component).toBeTruthy(); }); // 其余测试用例遵循相同逻辑:先配置对应Spy的返回值,再调用detectChanges触发执行 })
内容的提问来源于stack exchange,提问作者Jeremy Thomas
相关产品推荐
相关产品推荐

