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

Angular中如何模拟/覆写基类中定义的方法?

问题描述

我有一个基类,包含如下方法:

public handleError(){
 //some code
}

目前我正在为继承该基类的子组件编写测试用例,由于某些事件链,测试过程会执行上述方法并返回错误。

我该如何覆写/存根(stub)这个方法?

我尝试使用stub()和callFake()来拦截该方法,但执行流程仍会进入基类中定义的方法:

it('Should call super ngOnInit()', async () => {
  const { instance } = await shallow.render();

  spyOn(instance, 'handleError').and.callFake(()=>{
    return "error"
  });
  //spyOn(service, 'myMethod').and.stub();

  const SuperNgOnInitSpy = spyOnSuper(ListBase, 'ngOnInit');
  instance.ngOnInit();

  expect(SuperNgOnInitSpy).toHaveBeenCalled();
});
解决方案

问题核心在于spyOn默认只能存根实例自身拥有的方法,而handleError是定义在基类上的,子组件实例并未重写该方法,所以直接spy实例的方法不会生效。可以用以下两种方式解决:

方式一:存根基类的原型方法

直接在基类的原型上创建spy,这样所有继承该基类的实例都会被拦截:

it('Should call super ngOnInit()', async () => {
  const { instance } = await shallow.render();

  // 存根基类原型上的handleError方法
  const handleErrorSpy = spyOn(ListBase.prototype, 'handleError').and.callFake(() => {
    return "error";
  });

  const SuperNgOnInitSpy = spyOnSuper(ListBase, 'ngOnInit');
  instance.ngOnInit();

  expect(SuperNgOnInitSpy).toHaveBeenCalled();
  expect(handleErrorSpy).toHaveBeenCalled(); // 可验证方法是否被触发
});

方式二:动态重写子组件实例的方法

如果不想影响其他基类实例的测试,可以在获取子组件实例后直接覆盖该方法:

it('Should call super ngOnInit()', async () => {
  const { instance } = await shallow.render();

  // 直接覆盖当前实例的handleError方法
  instance.handleError = () => {
    return "error";
  };

  const SuperNgOnInitSpy = spyOnSuper(ListBase, 'ngOnInit');
  instance.ngOnInit();

  expect(SuperNgOnInitSpy).toHaveBeenCalled();
});

额外注意

如果使用Jasmine或Jest这类测试框架,建议在每个测试用例结束后清理spy,避免影响其他测试:

afterEach(() => {
  // Jasmine 写法
  spyOnRestore(ListBase.prototype.handleError);
  // 或 Jest 写法
  jest.clearAllMocks();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 02:47:20