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

Angular单元测试:Mock HTML Document测试print方法

Angular组件print方法单元测试:Mock Document与iframe并验证打印触发

针对你在Angular组件中实现的print方法,下面是具体的单元测试方案,包括Mock HTML Document和iframe,以及验证打印操作是否被正确触发:

核心思路

我们需要模拟document.getElementById("iframe0")返回的iframe元素,同时给该iframe的contentWindow.print()方法创建一个间谍(spy),这样就能追踪这个打印方法是否被调用。

情况1:组件直接使用全局document

如果你的组件直接调用全局document(就像你现在的代码),可以通过Spy全局document.getElementById来返回模拟的iframe:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyComponent } from './my.component';

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  let mockPrintSpy: jasmine.Spy;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [MyComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;

    // 1. 创建模拟的print方法间谍
    mockPrintSpy = jasmine.createSpy('print');
    // 2. 创建模拟的iframe对象,包含带spy的contentWindow.print
    const mockIframe = {
      contentWindow: {
        print: mockPrintSpy
      }
    };
    // 3. Mock全局document.getElementById,让它返回模拟的iframe
    spyOn(document, 'getElementById').and.returnValue(mockIframe as HTMLElement);
  });

  it('should call iframe contentWindow.print() when print() is invoked', () => {
    // 调用组件的print方法(参数i可随意传入,你的方法中未使用该参数)
    component.print(1);

    // 验证document.getElementById是否传入了正确的iframe ID
    expect(document.getElementById).toHaveBeenCalledWith('iframe0');
    // 验证打印方法是否被触发
    expect(mockPrintSpy).toHaveBeenCalled();
  });
});

情况2:组件依赖注入DOCUMENT(更规范的做法)

推荐将document通过Angular的依赖注入机制引入组件,这样更利于测试和维护:

调整组件代码:

import { Component, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Component({
  selector: 'app-my',
  templateUrl: './my.component.html'
})
export class MyComponent {
  constructor(@Inject(DOCUMENT) private document: Document) {}

  print(i: number) {
    (this.document.getElementById("iframe0") as any).contentWindow.print();
  }
}

对应的单元测试:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyComponent } from './my.component';
import { DOCUMENT } from '@angular/common';

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  let mockPrintSpy: jasmine.Spy;
  let mockDocument: any;

  beforeEach(async () => {
    // 提前创建模拟的print间谍和document对象
    mockPrintSpy = jasmine.createSpy('print');
    mockDocument = {
      getElementById: jasmine.createSpy('getElementById').and.returnValue({
        contentWindow: { print: mockPrintSpy }
      })
    };

    await TestBed.configureTestingModule({
      declarations: [MyComponent],
      providers: [
        { provide: DOCUMENT, useValue: mockDocument }
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
  });

  it('should trigger iframe print via injected document', () => {
    component.print(0);

    expect(mockDocument.getElementById).toHaveBeenCalledWith('iframe0');
    expect(mockPrintSpy).toHaveBeenCalled();
  });
});

关键说明

  • 我们用jasmine.createSpy创建了print方法的间谍,目的是追踪该方法是否被调用,无需实际触发浏览器的打印弹窗。
  • 通过MockgetElementById,让组件代码获取到我们预设的iframe模拟对象,从而将测试与真实DOM环境解耦。
  • 测试用例中需要验证两个点:一是getElementById是否传入了正确的ID("iframe0"),二是print方法是否被执行。

内容的提问来源于stack exchange,提问作者Edson Barbosa Junior

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 10:50:28