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);
如果您想重新表述,必须删除之前的问题:
我设置了这个组件:
@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);