You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 05:25:44