angular 6 unittest, observable of() 是同步的

angular 6 unittest, observable of() is synchronous

如果您想重新表述,必须删除之前的问题:

我设置了这个组件:

@Component({
  selector: 'app-async',
  templateUrl: './async.component.html',
  styleUrls: ['./async.component.scss']
})
export class AsyncComponent implements OnInit {

  title$: Observable<string>;
  constructor(private stringService: AsyncStringService) { }

  ngOnInit() {
    this.title$ = this.stringService.getString();
  }
}

其中 AsyncStringService.getString 是这样的:

getString(): Observable<string>

组件的模板是:

<h1 id="title">{{title$ | async}}</h1>

我想使用 jasmines 异步功能测试组件行为,但如果我不考虑任何异步延续,我的测试也有效:

describe('AsyncComponent', () => {
  let fixture: ComponentFixture<AsyncComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ AsyncComponent ],
      providers: [ AsyncStringService ]
    })
    .compileComponents().then(() =>
      fixture = TestBed.createComponent(AsyncComponent));

  }));

  it('should not have resolved observable immedeatly', () => {
    const spy = spyOn(fixture.debugElement.injector.get(AsyncStringService), 'getString')
      .and.returnValue(of( 'value 1'));
    fixture.detectChanges();
    expect(fixture.debugElement.query(By.css('#title')).nativeElement.innerText).toEqual('value 1');
  });

  it('should have all observables resolved in whenStable', async(() => {
    const spy = spyOn(fixture.debugElement.injector.get(AsyncStringService), 'getString')
      .and.returnValue(of( 'value 1'));
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      fixture.detectChanges();
      expect(fixture.debugElement.query(By.css('#title')).nativeElement.innerText).toEqual('value 1');
    });
  }));


  it('should have all observables resolved when ticking', fakeAsync(() => {
    const spy = spyOn(fixture.debugElement.injector.get(AsyncStringService), 'getString')
      .and.returnValue(of( 'value 1'));
    fixture.detectChanges();
    tick();

    expect(fixture.debugElement.query(By.css('#title')).nativeElement.innerText).toEqual('value 1');
  }));
});

所有三个测试都成功,我希望间谍 return 一个未通过第一个测试的可观察对象,因为它没有考虑异步性。

此外,如果我不正确地使用这些功能(async / fakeAsync),请提供任何提示!

编辑:

我尝试了 of('value 1').pipe(delay(100)),这会导致所有测试失败。我假设这以某种方式连接到 async/fakeAsync 流未看到的异步管道?

编辑:

我的同步任务失败了,而 done() 和 async() 通过 returning timer(10).pipe(map(() => 'value 1')) 从我的间谍那里经过。

假的异步测试却表现得很奇怪:

如果我检查订阅者中的可观察值,它就会通过,即使我根本不调用 tick() - 所以时间不应该流逝,时间也不应该发出值。

并调用 tick(100),这应该使 time(10) 发出,不会导致值落在订阅者之外的模板中。

 it('should have all observables resolved when ticking the appropriate amount of time', fakeAsync(() => {
    const spy = spyOn(fixture.debugElement.injector.get(AsyncStringService), 'getString')
      .and.returnValue(timer(10).pipe(map(() => 'value 1')));
    fixture.componentInstance.ngOnInit();
    fixture.componentInstance.title$.subscribe(value => expect(value).toEqual('value 1'));
    fixture.componentInstance.title$.subscribe(() => {
      fixture.detectChanges();
      expect(fixture.debugElement.query(By.css('#title')).nativeElement.innerText).toEqual('value 1');
    });
    tick(100); // this does nothing
    fixture.detectChanges();
    expect(fixture.debugElement.query(By.css('#title')).nativeElement.innerText).toEqual('value 1');
    discardPeriodicTasks();
  }));

我通过将异步调度程序作为第二个参数传递给 of():

import {async as _async} from 'rxjs/scheduler/async';

var stub$ = of(stub, _async);