【问题标题】:Angular testing async pipe does not trigger the observable角度测试异步管道不会触发可观察的
【发布时间】:2017-06-29 09:36:49
【问题描述】:

我想测试一个使用异步管道的组件。这是我的代码:

@Component({
  selector: 'test',
  template: `
    <div>{{ number | async }}</div>
  `
})
class AsyncComponent {
  number = Observable.interval(1000).take(3)
}

fdescribe('Async Compnent', () => {
  let component : AsyncComponent;
  let fixture : ComponentFixture<AsyncComponent>;

  beforeEach(
    async(() => {
      TestBed.configureTestingModule({
        declarations: [ AsyncComponent ]
      }).compileComponents();
    })
  );

  beforeEach(() => {
    fixture = TestBed.createComponent(AsyncComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });


  it('should emit values', fakeAsync(() => {

    tick(1000);
    fixture.detectChanges();
    expect(fixture.debugElement.query(By.css('div')).nativeElement.innerHTML).toBe('0');

});

但是测试失败了。由于某种原因,Angular 似乎没有对 Observable 执行。我错过了什么?

当我尝试使用 do 运算符记录 observable 时,我在浏览器控制台中看不到任何输出。

【问题讨论】:

    标签: javascript angular testing


    【解决方案1】:

    据我所知,您不能将fakeAsync 与异步管道一起使用。我很想被证明是错误的,但我尝试了一段时间,却没有任何效果。相反,请使用async 实用程序(我将其别名为realAsync 以避免与async 关键字混淆)和await 一个Promise 包装的setTimeout,而不是使用tick

    import { async as realAsync, ComponentFixture, TestBed } from '@angular/core/testing';
    
    import { AsyncComponent } from './async.component';
    
    function setTimeoutPromise(milliseconds: number): Promise<void> {
      return new Promise((resolve) => { 
        setTimeout(resolve, milliseconds);
      });
    }
    
    describe('AsyncComponent', () => {
      let component: AsyncComponent;
      let fixture: ComponentFixture<AsyncComponent>;
      let element: HTMLElement;
    
      beforeEach(realAsync(() => {
        TestBed.configureTestingModule({
          declarations: [ AsyncComponent ]
        })
        .compileComponents();
      }));
    
      beforeEach(() => {
        fixture = TestBed.createComponent(AsyncComponent);
        component = fixture.componentInstance;
        element = fixture.nativeElement;
        fixture.detectChanges();
      });
    
      it('should emit values', realAsync(async () => {
        await setTimeoutPromise(1000);
        fixture.detectChanges();
        expect(element.getElementsByTagName('div')[0].innerHTML).toEqual('0');
      }));
    });
    

    【讨论】:

    • 谢谢,这实际上是为我做的!但是fixture.detectChanges();也是有帮助的。我和你一样,在 beforeChanges 结束时已经有一个,但这还不够
    • 对于使用async 管道的组件,您绝对可以使用fakeAsync 测试。也许您遇到的问题与某些需要在正确的时间刷新微任务队列有关?我使用我为组件测试创建的助手,它通常会为我处理所有这些细节:ComponentContextNext
    • 谢谢,这种方法非常有效!
    【解决方案2】:

    我遇到了这个问题,我很惊讶没有人找到任何真正的解决方案。

    可能的解决方案

    • 您的模板可能不会在您的测试中呈现,尤其是当您覆盖它时。所以,|不会触发异步操作。
    • 您使用的fixture.detectChanges() 不足以允许模板呈现。渲染发生在 OnInit 阶段之后。因此,请确保您至少使用了 2 次 fixture.detectChanges。
    • 也许您有 setTimeout 操作待处理,例如 debounce(100) 需要 tick(100) 来解决(在 fakeAsync 测试中)。

    干杯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 2020-07-27
      • 1970-01-01
      • 1970-01-01
      • 2020-08-29
      相关资源
      最近更新 更多