Angular+Jest测试报错:TypeError: this.helperService.add不是函数
解决Angular测试中
TypeError: this.helperService.add is not a function错误 错误原因
- 你在
TestBed的providers数组中重复注册了HelperService,后一个{provide: HelperService, useValue: subSpy}会覆盖前一个配置,最终注入到TestService的是subSpy——它只是subtract方法的spy函数,并非完整的HelperService实例,自然不存在add方法。 - 直接将
jest.spyOn返回的单个方法spy作为useValue注入是错误逻辑,TestService依赖的是HelperService的完整实例,而非单个孤立的方法spy。
解决方案
方法一:创建包含spy方法的模拟服务实例
在beforeEach中构建一个模拟的HelperService对象,为其add和subtract方法分别设置spy,再将这个模拟对象作为依赖注入:
import { TestBed } from '@angular/core/testing'; import { HelperService } from './helper.service'; import { TestService } from './test.service'; describe('Test Service', () => { let testService: TestService; let mockHelperService: jest.Mocked<HelperService>; beforeEach(() => { // 构建模拟服务,包含两个方法的spy mockHelperService = { add: jest.fn().mockReturnValue(50), subtract: jest.fn() } as jest.Mocked<HelperService>; TestBed.configureTestingModule({ providers: [ TestService, { provide: HelperService, useValue: mockHelperService } ], }); testService = TestBed.inject(TestService); }); it('should be created', () => { expect(testService).toBeTruthy(); }); it('should add two numbers', () => { const result = testService.add(25, 25); expect(result).toBe(50); // 额外验证spy是否被正确调用 expect(mockHelperService.add).toHaveBeenCalledWith(25, 25); }); });
方法二:注入真实服务后对方法打spy
如果需要保留真实HelperService的部分逻辑(本案例中虽无必要,但方法具备通用性),可以先注入真实服务实例,再对目标方法打spy:
import { TestBed } from '@angular/core/testing'; import { HelperService } from './helper.service'; import { TestService } from './test.service'; describe('Test Service', () => { let testService: TestService; let helperService: HelperService; let addSpy: jest.SpyInstance; let subSpy: jest.SpyInstance; beforeEach(() => { TestBed.configureTestingModule({ providers: [TestService, HelperService] }); testService = TestBed.inject(TestService); helperService = TestBed.inject(HelperService); // 对真实服务实例的方法打spy addSpy = jest.spyOn(helperService, 'add').mockReturnValue(50); subSpy = jest.spyOn(helperService, 'subtract'); }); // 测试后恢复原始方法,避免影响其他测试用例 afterEach(() => { addSpy.mockRestore(); subSpy.mockRestore(); }); it('should be created', () => { expect(testService).toBeTruthy(); }); it('should add two numbers', () => { const result = testService.add(25, 25); expect(result).toBe(50); expect(addSpy).toHaveBeenCalledWith(25, 25); }); });
内容的提问来源于stack exchange,提问作者Anis83
相关产品推荐
相关产品推荐

