Angular 8 个单元测试指令,其中包括 setTimeout
Angular 8 unit test directive which includes setTimeout
我有以下简单的自动对焦指令:
@Directive({
selector: '[appAutoFocus]',
})
export class AutofocusDirective implements AfterContentInit {
@Input() public appAutoFocus: boolean;
public constructor(private el: ElementRef) { }
public ngAfterContentInit() {
if (this.appAutoFocus) {
setTimeout(() => {
this.el.nativeElement.focus();
}, 300);
}
}
}
我现在正在尝试编写一些简单的单元测试,但是 3 个测试中有 2 个失败了。
@Component({
template: '<input type="text" [appAutoFocus]="true" />'
})
class TestComponent {
constructor() { }
}
fdescribe('AutoFocusDirective', () => {
let component: TestComponent;
let fixture: ComponentFixture<TestComponent>;
let inputEl: DebugElement;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
TestComponent,
AutofocusDirective
]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
inputEl = fixture.debugElement.query(By.css('input'));
spyOn(inputEl.nativeElement, 'focus');
fixture.detectChanges();
});
it('should create an instance', () => {
expect(component).toBeTruthy();
});
it('should call the focus event', fakeAsync(() => {
tick(400);
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(inputEl.nativeElement.focus).toHaveBeenCalled();
});
}));
it('should autofocus the input control', () => {
const debugEl: DebugElement = fixture.debugElement;
expect(debugEl.query(By.css('input:focus'))).not.toBe(null);
});
"Should call the focus event" 失败 Spec 'AutoFocusDirective should call the focus event' has no expectations.
"Should autofocus the input control" 失败 Expected null not to be null
也许你不能将 fakeAsync
与 fixture.whenStable
结合起来。
尝试:
it('should call the focus event', fakeAsync(() => {
tick(400);
fixture.detectChanges();
// You should check out `flush` method to resolve instead of specifying the time in the argument of tick
expect(inputEl.nativeElement.focus).toHaveBeenCalled();
}));
it('should autofocus the input control', fakeAsync(() => {
tick(400);
fixture.detectChanges();
const debugEl: DebugElement = fixture.debugElement;
expect(debugEl.query(By.css('input:focus'))).not.toBe(null);
}));
你的两个测试做同样的事情,所以考虑把它们放在一个 it
块中。
适合您的读物:https://alligator.io/angular/testing-async-fakeasync/
我能让它工作的唯一方法是在测试规范中添加一个 setTimeout,所以它现在看起来像这样:
it('should call the focus event', (done) => {
fixture.detectChanges();
setTimeout(() => {
expect(inputEl.nativeElement.focus).toHaveBeenCalled();
done();
}, 500);
});
老实说,这是一个垃圾解决方案,但我在这上面浪费了太多时间。
我有以下简单的自动对焦指令:
@Directive({
selector: '[appAutoFocus]',
})
export class AutofocusDirective implements AfterContentInit {
@Input() public appAutoFocus: boolean;
public constructor(private el: ElementRef) { }
public ngAfterContentInit() {
if (this.appAutoFocus) {
setTimeout(() => {
this.el.nativeElement.focus();
}, 300);
}
}
}
我现在正在尝试编写一些简单的单元测试,但是 3 个测试中有 2 个失败了。
@Component({
template: '<input type="text" [appAutoFocus]="true" />'
})
class TestComponent {
constructor() { }
}
fdescribe('AutoFocusDirective', () => {
let component: TestComponent;
let fixture: ComponentFixture<TestComponent>;
let inputEl: DebugElement;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
TestComponent,
AutofocusDirective
]
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
inputEl = fixture.debugElement.query(By.css('input'));
spyOn(inputEl.nativeElement, 'focus');
fixture.detectChanges();
});
it('should create an instance', () => {
expect(component).toBeTruthy();
});
it('should call the focus event', fakeAsync(() => {
tick(400);
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(inputEl.nativeElement.focus).toHaveBeenCalled();
});
}));
it('should autofocus the input control', () => {
const debugEl: DebugElement = fixture.debugElement;
expect(debugEl.query(By.css('input:focus'))).not.toBe(null);
});
"Should call the focus event" 失败 Spec 'AutoFocusDirective should call the focus event' has no expectations.
"Should autofocus the input control" 失败 Expected null not to be null
也许你不能将 fakeAsync
与 fixture.whenStable
结合起来。
尝试:
it('should call the focus event', fakeAsync(() => {
tick(400);
fixture.detectChanges();
// You should check out `flush` method to resolve instead of specifying the time in the argument of tick
expect(inputEl.nativeElement.focus).toHaveBeenCalled();
}));
it('should autofocus the input control', fakeAsync(() => {
tick(400);
fixture.detectChanges();
const debugEl: DebugElement = fixture.debugElement;
expect(debugEl.query(By.css('input:focus'))).not.toBe(null);
}));
你的两个测试做同样的事情,所以考虑把它们放在一个 it
块中。
适合您的读物:https://alligator.io/angular/testing-async-fakeasync/
我能让它工作的唯一方法是在测试规范中添加一个 setTimeout,所以它现在看起来像这样:
it('should call the focus event', (done) => {
fixture.detectChanges();
setTimeout(() => {
expect(inputEl.nativeElement.focus).toHaveBeenCalled();
done();
}, 500);
});
老实说,这是一个垃圾解决方案,但我在这上面浪费了太多时间。