如何使用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
相关产品推荐
相关产品推荐

