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

Angular单元测试中如何Mock继承类?问题求助

问题分析与解决方案

你遇到的核心问题是:EntityApi直接继承了BaseApi,当TestBed创建EntityApi实例时,它会直接调用真实BaseApi的构造函数,完全绕开你配置的BaseApiStub。TestBed里的{ provide: BaseApi, useClass: BaseApiStub }只在代码通过依赖注入直接请求BaseApi实例时生效,而子类继承父类的场景下,父类构造函数是被子类直接调用的,不走依赖注入流程,所以你的Stub根本没被触发。

下面给你两种可行的修正方案:


方案一:直接Mock EntityApi(最简单直接)

既然组件依赖的是EntityApi,我们直接替换这个服务的实现,完全跳过真实的EntityApi和BaseApi,这是单元测试隔离依赖的常规操作:

步骤1:创建EntityApiStub

export class EntityApiStub {
  constructor() {
    console.log("You are on track!!");
  }
  // 可以添加组件需要调用的方法,比如get()
  get() {
    return Promise.resolve([]); // 模拟返回数据
  }
}

步骤2:修改测试配置

在TestBed.configureTestingModule的providers里替换EntityApi:

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [EntityListComponent],
    providers: [
      // 直接把EntityApi替换为我们的Stub
      { provide: EntityApi, useClass: EntityApiStub }
    ],
    schemas: [NO_ERRORS_SCHEMA]
  }).compileComponents();

  // 注意:你之前把beforeEach和it写在了async的回调里,这是语法错误!要把它们移出来
  beforeEach(() => {
    fixture = TestBed.createComponent(EntityListComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
}));

这样TestBed会给组件注入EntityApiStub实例,控制台会输出你预期的日志,测试也能正常通过。


方案二:重构依赖方式(适合长期维护)

如果你的项目中有多个类似EntityApi的子类,都需要Mock父类BaseApi,可以重构代码让父类通过依赖注入传入,而不是直接继承:

步骤1:修改业务代码

// BaseApi保持不变
export class BaseApi {
  constructor(injector: Injector, private endpoint: string) {
    console.log("Should not be here...");
  }
}

// 把EntityApi改成依赖注入BaseApi,而非继承
@Injectable()
export class EntityApi {
  constructor(private baseApi: BaseApi) {}
  
  // 复用BaseApi的方法,比如:
  get() {
    return this.baseApi.get();
  }
}

步骤2:修改测试配置

这时你原来的BaseApiStub配置就会生效了:

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [EntityListComponent],
    providers: [
      { provide: BaseApi, useClass: BaseApiStub },
      EntityApi // 现在EntityApi会依赖注入Stub版本的BaseApi
    ],
    schemas: [NO_ERRORS_SCHEMA]
  }).compileComponents();
}));

这种方式需要修改业务代码,但能让父类的Mock更灵活,适合复杂场景。


另外提醒你一个语法错误:你之前把内层的beforeEach和it写在了async(() => {})的回调函数里,这会导致测试逻辑无法正常执行,一定要把它们移到async回调外面。

内容的提问来源于stack exchange,提问作者Premkumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:59:20