【问题标题】:Angular 8 unit test directive which includes setTimeoutAngular 8 单元测试指令,其中包括 setTimeout
【发布时间】:2020-02-19 17:05:17
【问题描述】:

我有以下简单的自动对焦指令:

@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);
      });

“应该调用焦点事件”失败,Spec 'AutoFocusDirective should call the focus event' has no expectations.

“应自动聚焦输入控件”失败并显示 Expected null not to be null

【问题讨论】:

    标签: angular jasmine


    【解决方案1】:

    也许你不能将fakeAsyncfixture.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 回调中,输入console.log('In the set timeout')console.log('inside of the if function') 并确保两个日志都可见。
    【解决方案2】:

    我可以让它工作的唯一方法是在测试规范中添加一个 setTimeout,所以它现在看起来像这样:

      it('should call the focus event', (done) => {
        fixture.detectChanges();
        setTimeout(() => {
          expect(inputEl.nativeElement.focus).toHaveBeenCalled();
          done();
        }, 500);
      });
    

    说实话,这是一个垃圾解决方案,但我在这上面浪费了太多时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-18
      • 2021-09-25
      • 1970-01-01
      • 2015-01-18
      • 2012-11-10
      • 2016-04-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多