How to write the unit testing for the file upload method in the Angular 7 (or 2+)
我正在尝试为 Angular 7 中的文件上传方法编写单元测试。在测试窗口中出现以下错误。我是angular单元测试的新手。有人可以帮忙,如何添加模拟文件以获得完整的代码覆盖率?
TypeError: Cannot set property 'value' of undefined
这是我的单元测试代码(规范文件),
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | describe('ImportComponent', () => { let component: ImportComponent; let fixture: ComponentFixture<ImportComponent>; let element; beforeEach( async(() => { TestBed.configureTestingModule({ imports: [ HttpClientModule, RouterTestingModule ], declarations: [ ImportComponent ] }).compileComponents(); }) ); beforeEach(() => { fixture = TestBed.createComponent(ImportComponent); component = fixture.componentInstance; element = fixture.nativeElement; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); it('should upload the file', () => { component.importFile(); const inputEl = element.querySelector('#postal_file'); const fileList = { 0: { name: 'foo', size: 500001 } }; inputEl.value = { target: { files: fileList } }; inputEl.dispatchEvent(new Event('change')); }); }); |
组件中的方法
1 2 3 4 5 6 7 8 9 10 11 | importFile() { const inputEl: HTMLInputElement = this.el.nativeElement.querySelector('#postal_file'); const fileCount: number = inputEl.files.length; const formData = new FormData(); if (fileCount > 0) { formData.append(this.postalFileName, inputEl.files.item(0)); this.postalService.importPostalCodes(formData).subscribe((data) => { this.result = data; }); } } |
和 HTML,
1 2 3 4 5 | <form action="" method="post" encType="multipart/form-data"> <label for="postal_file">Choose File</label> <input type="file" name="postal_file" id="postal_file"> <button type="button" (click)="importFile()">Import</button> </form> |
单元测试没有覆盖下图所示的所有代码,请帮忙,如何获得100%的代码覆盖率。
代码覆盖率图片
测试文件上传和检查模型值集的简单方法。
.html
1 | <input (change)="onFileSelected()" #fileInput type="file" id="file"> |
.ts
1 2 3 4 5 6 | uploadedFile : any onFileSelected() { const inputNode: any = document.querySelector('#file'); this.uploadedFile = inputNode.files[0]; } |
spec.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | it('should detect file input change and set uploadedFile model', () => { const dataTransfer = new DataTransfer() dataTransfer.items.add(new File([''], 'test-file.pdf')) const inputDebugEl = fixture.debugElement.query(By.css('input[type=file]')); inputDebugEl.nativeElement.files = dataTransfer.files; inputDebugEl.nativeElement.dispatchEvent(new InputEvent('change')); fixture.detectChanges(); expect(component.uploadedFile).toBeTruthy() expect(component.uploadedFile).toBe('test-file.pdf') }); it('file change event should arrive in handler', () => { const element = fixture.nativeElement; const input = element.querySelector('#file'); spyOn(component, 'onFileSelected'); input.dispatchEvent(new Event('change')); fixture.detectChanges(); expect(component.onFileSelected).toHaveBeenCalled(); }); |
对于上述部分的 100% 代码覆盖率,我在下面添加了 2 个测试用例。这对我有用。
1 2 3 4 5 6 7 8 9 10 11 12 13 | it('should upload the file - checkFileExist = true', () => { spyOn(component, 'checkFileExist').and.returnValue(true); spyOn(postalService,'importPostalCodes').and.callThrough(); component.importFile(); expect(postalService.importPostalCodes).toHaveBeenCalled(); }); it('should upload the file - checkFileExist = false', () => { spyOn(component, 'checkFileExist').and.returnValue(false); spyOn(postalService,'importPostalCodes').and.callThrough(); component.importFile(); expect(postalService.importPostalCodes).toHaveBeenCalledTimes(0); }); |