【问题标题】:How to unit test a button click event in Angular?如何在Angular中对按钮单击事件进行单元测试?
【发布时间】:2026-01-11 14:40:01
【问题描述】:

我正在尝试测试按钮单击事件。 Angular 官方手册说有两种方法可以做到这一点。

1.

it('should raise selected event when clicked (triggerEventHandler)', () => {
  let selectedHero: Hero;
  const heroDe = fixture.debugElement.query(By.css('dashboard-hero'));
  comp.selected.subscribe((hero: Hero) => selectedHero = hero);
  heroDe.triggerEventHandler('click', null);
  expect(selectedHero).toBe(expectedHero);
});
it('should raise selected event when clicked (element.click)', () => {
  let selectedHero: Hero;
  const heroEl: HTMLElement = fixture.nativeElement.querySelector('.hero');
  comp.selected.subscribe((hero: Hero) => selectedHero = hero);
  heroEl.click();
  expect(selectedHero).toBe(expectedHero);
});

第一种方法对我来说效果很好。但是当我尝试第二个选项时,测试运行没有错误,但 Karma 开始在无限循环中运行测试。

这是我对这两种方式的实现。

it('test1', () => {
  fixture.detectChanges();
  let treeNodeElement = fixture.debugElement.query(By.css('#buttonSend'));
  treeNodeElement.triggerEventHandler('click', null);
  expect(component.tabService.tabs.length).toBe(1);
  expect(component.tabService.tabs[0].title).toBe('Test1');
});

it('test2', () => {
  fixture.detectChanges();
  const treeNodeElement: HTMLElement = fixture.nativeElement.querySelector('#buttonSend');
  treeNodeElement.click();
  expect(component.tabService.tabs.length).toBe(1);
  expect(component.tabService.tabs[0].title).toBe('Test1');
});

你能告诉我第二个选项的错误在哪里吗?

【问题讨论】:

  • 有什么解决办法吗?我也有同样的问题。

标签: angular unit-testing karma-jasmine


【解决方案1】:

我的解决方案是在 beforeEach() 中导入 FormsModuleReactiveFormsModule。 问题是单击按钮(这是一个提交按钮)会产生刷新页面的浏览器行为。 即使 FormsModule 和 ReactiveFormsModule 被导入到创建表单的组件中,它们也必须被导入到运行测试用例的 .spec 文件中

beforeEach(async () => {
 await TestBed.configureTestingModule({
  imports: [
    RouterTestingModule,
    RouterModule.forRoot([]),
    NgbModule,
    FormsModule,  <----
    ReactiveFormsModule,  <----
  ],
  declarations: [  
   ...

两个模块都应该从 @angular/forms 导入

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

【讨论】: