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

如何使用Jest为Angular中的指令编写单元测试?

Angular DragDropDirective Jest单元测试实现

测试文件基础结构

先创建对应测试文件(比如drag-drop.directive.spec.ts),配置TestBed并获取指令实例:

import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DragDropDirective } from './drag-drop.directive';
import { By } from '@angular/platform-browser';

// 用于挂载指令的测试组件
@Component({
  template: `<div appDragDrop></div>`
})
class TestDragDropComponent {}

describe('DragDropDirective', () => {
  let fixture: ComponentFixture<TestDragDropComponent>;
  let directive: DragDropDirective;
  let hostElement: DebugElement;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [DragDropDirective, TestDragDropComponent]
    });

    fixture = TestBed.createComponent(TestDragDropComponent);
    hostElement = fixture.debugElement.query(By.directive(DragDropDirective));
    directive = hostElement.injector.get(DragDropDirective);
    fixture.detectChanges();
  });

  // 测试用例写在这里
});

测试用例详解

1. 当enabled为false时,拖拽方法直接返回不执行后续逻辑

it('should skip drag logic when enabled is false', () => {
  directive.enabled = false;
  
  const mockEvent = {
    dataTransfer: { dropEffect: '', effectAllowed: '' },
    stopPropagation: jest.fn(),
    preventDefault: jest.fn()
  } as unknown as DragEvent;

  directive.handleDragOver(mockEvent);
  directive.handleDragEnd(mockEvent);

  expect(mockEvent.stopPropagation).not.toHaveBeenCalled();
  expect(mockEvent.preventDefault).not.toHaveBeenCalled();
  expect(directive['_dragInProgress']).toBe(false);
});

2. 当enabled为true时,handleDragOver执行正确逻辑

it('should set dragInProgress to true and configure dropEffect in handleDragOver', () => {
  directive.enabled = true;
  
  const mockEvent = {
    dataTransfer: { dropEffect: '' },
    stopPropagation: jest.fn(),
    preventDefault: jest.fn()
  } as unknown as DragEvent;

  const stopSpy = jest.spyOn(directive, 'stopAndPreventDefault');

  directive.handleDragOver(mockEvent);

  expect(directive['_dragInProgress']).toBe(true);
  expect(mockEvent.dataTransfer?.dropEffect).toBe('move');
  expect(stopSpy).toHaveBeenCalledWith(mockEvent);
});

3. 当enabled为true时,handleDragEnd执行正确逻辑

it('should set dragInProgress to false and configure effectAllowed in handleDragEnd', () => {
  directive.enabled = true;
  directive['_dragInProgress'] = true;
  
  const mockEvent = {
    dataTransfer: { effectAllowed: '' },
    stopPropagation: jest.fn(),
    preventDefault: jest.fn()
  } as unknown as DragEvent;

  const stopSpy = jest.spyOn(directive, 'stopAndPreventDefault');

  directive.handleDragEnd(mockEvent);

  expect(directive['_dragInProgress']).toBe(false);
  expect(mockEvent.dataTransfer?.effectAllowed).toBe('copy');
  expect(stopSpy).toHaveBeenCalledWith(mockEvent);
});

4. 验证stopAndPreventDefault方法正确调用事件阻止方法

it('should trigger stopPropagation and preventDefault on the event', () => {
  const mockEvent = {
    stopPropagation: jest.fn(),
    preventDefault: jest.fn()
  } as unknown as UIEvent;

  directive.stopAndPreventDefault(mockEvent);

  expect(mockEvent.stopPropagation).toHaveBeenCalled();
  expect(mockEvent.preventDefault).toHaveBeenCalled();
});

关键注意点

  • 私有属性_dragInProgress可通过directive['_dragInProgress']访问(Jest支持这种方式)
  • 模拟DragEvent时需用unknown as DragEvent做类型断言,规避TypeScript类型报错
  • 使用jest.spyOn监听方法调用,验证是否被正确触发

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 06:37:37