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

Angular中如何Mock动态加载的子组件?私有函数测试场景

如何在测试中替换动态导入的组件为Mock组件

针对你给出的私有异步函数,要在测试时替换动态加载的ProductErrorPageContainer为Mock组件,可按以下两种常用方式实现:

方法1:用Jest Mock拦截动态导入(推荐)

这种方式直接拦截模块导入请求,让函数加载Mock组件而非真实组件:

  1. 定义Mock组件
    创建一个极简的Mock组件替代真实组件:

    import { Component } from '@angular/core';
    
    @Component({ selector: 'app-product-error-page', template: '' })
    export class MockProductErrorPageContainer {}
    
  2. Mock目标模块
    在测试文件顶部添加Mock配置,覆盖真实模块的导出:

    jest.mock('../../lazy/product-error-page/product-error-page.container', () => ({
      ProductErrorPageContainer: MockProductErrorPageContainer
    }));
    
  3. 编写测试用例
    调用私有函数并验证逻辑,测试时可通过(component as any)访问私有成员:

    import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
    import { YourComponent } from './your.component';
    import { MockProductErrorPageContainer } from './mock-components';
    
    describe('YourComponent', () => {
      let component: YourComponent;
      let fixture: ComponentFixture<YourComponent>;
    
      beforeEach(async () => {
        await TestBed.configureTestingModule({
          declarations: [YourComponent, MockProductErrorPageContainer]
        }).compileComponents();
      });
    
      beforeEach(() => {
        fixture = TestBed.createComponent(YourComponent);
        component = fixture.componentInstance;
        // Mock productErrorPageTemplate 对象
        component.productErrorPageTemplate = {
          clear: jest.fn(),
          createComponent: jest.fn(factory => {
            // 验证加载的是Mock组件
            expect(factory.componentType).toBe(MockProductErrorPageContainer);
            return { instance: {} };
          })
        };
        fixture.detectChanges();
      });
    
      it('should load Mock component when loadPageNotFoundContainer runs', fakeAsync(async () => {
        // 调用私有函数
        await (component as any).loadPageNotFoundContainer();
        tick(); // 处理异步流程
    
        // 验证前置逻辑和组件创建行为
        expect(component.productErrorPageTemplate.clear).toHaveBeenCalled();
        expect(component.productErrorPageTemplate.createComponent).toHaveBeenCalled();
      }));
    });
    

方法2:通过Angular TestBed覆盖组件工厂

如果不用Jest,可通过ComponentFactoryResolver的Mock实例返回Mock组件的工厂:

  1. 定义Mock组件(同方法1)

  2. 配置TestBed并Mock ComponentFactoryResolver

    import { ComponentFactoryResolver } from '@angular/core';
    
    beforeEach(async () => {
      const mockCfr = jasmine.createSpyObj('ComponentFactoryResolver', ['resolveComponentFactory']);
      // 让resolveComponentFactory返回Mock组件的工厂
      mockCfr.resolveComponentFactory.and.returnValue({
        componentType: MockProductErrorPageContainer
      } as any);
    
      await TestBed.configureTestingModule({
        declarations: [YourComponent, MockProductErrorPageContainer],
        providers: [{ provide: ComponentFactoryResolver, useValue: mockCfr }]
      }).compileComponents();
    });
    
  3. 编写测试用例
    同样调用私有函数,验证resolveComponentFactory是否传入了Mock组件类型,以及模板的clear和createComponent方法是否被调用。

注意事项

  • 测试私有函数时,直接通过(component as any)访问是测试场景下的权宜之计,优先通过触发调用该私有函数的公共方法来测试(如果存在)。
  • 确保Mock组件的selector与真实组件一致,避免模板渲染异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:52:39