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
相关产品推荐
相关产品推荐

