Oro*_*dan 10 unit-testing asynchronous observable jasmine angular
我正在复制一些Angular文档的例子,以提高我对角度单元测试的理解,最后我在一个简单的测试用例中,当我无法弄清楚发生了什么.
这是我的app.component.ts文件,当我有一个方法"getQuote"从服务获得报价.
@Component({...})
export class AppComponent {
errMsg: string;
quote: Observable<string>;
constructor (private twainService: TwainService) {}
getQuote () {
this.quote = this.twainService.getQuote().pipe(
catchError(err => {
this.errMsg = err;
return of('...');
})
);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我创建了一个测试来验证我的errMsg道具是否正确更新,以防我从twainService.getQuote方法收到错误:
describe('AppComponent', () => {
let fixture: ComponentFixture<AppComponent>;
let component: AppComponent;
let getQuoteSpy;
beforeEach(async(() => {
const twainService = jasmine.createSpyObj('TwainService', ['getQuote']);
getQuoteSpy = twainService.getQuote.and.returnValue(of(testQuote));
TestBed.configureTestingModule({
declarations: [
AppComponent
],
providers: [
{ provide: TwainService, useValue: twainService }
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.debugElement.componentInstance;
});
it('should get error msg when TwainService fails', async(async () => {
const errMsg = 'TwainService fails';
getQuoteSpy.and.returnValue(throwError(errMsg));
component.getQuote();
await fixture.whenStable();
expect(component.errMsg).toBe(errMsg);
}));
});
Run Code Online (Sandbox Code Playgroud)
但问题是:这个测试总是失败,我无法看到什么是错的.
到处玩,我设法发现添加一个像"fixture.detectChanges()"这样的测试工作,但我不明白为什么.我认为detectChanges方法仅用于将更改传播到组件视图.
it('should get error msg when TwainService fails', async(async () => {
const errMsg = 'TwainService fails';
getQuoteSpy.and.returnValue(throwError(errMsg));
component.getQuote();
fixture.detectChanges();
await fixture.whenStable();
expect(component.errMsg).toBe(errMsg);
}));
Run Code Online (Sandbox Code Playgroud)
我测试了async,fakeAsync,并使用同步observable直接发送错误和异步observable,结果总是相同的.
如果有人能帮我理解那里发生了什么:)
我猜你只需要在测试中quote调用getQuote方法后订阅你的Observable :
it('should get error msg when TwainService fails', async(async () => {
const errMsg = 'TwainService fails';
getQuoteSpy.and.returnValue(throwError(errMsg));
component.getQuote();
component.quote.subscribe();
await fixture.whenStable();
expect(component.errMsg).toBe(errMsg);
}));
Run Code Online (Sandbox Code Playgroud)
因此,当您调用component.getQuote()测试时 - 它只是将this.quote属性设置为'冷'可观察,并且为了看到它catchError被触发,您必须订阅Observable.这将运行它,最终你会根据你的模拟数据得到一个错误throwError(errMsg).
编辑
根据你问题的第二部分:
到处玩,我设法发现添加一个像"fixture.detectChanges()"这样的测试工作,但我不明白为什么.
我也想通了,很可能你async在组件的模板中的某个地方使用了管道:{{ quote | async }}.在引擎盖下,angular的异步管道订阅了一个quoteObservable并返回它发出的最新值.这就是我们需要调用detectChanges方法的原因,之后 - 异步管道将开始订阅quoteObservable(并且测试将按预期工作).在这种情况下,我们不需要手动订阅quoteObservable(异步管道处理它).是的 - 你是对的:我认为detectChanges方法仅用于将更改传播到组件视图.
您可以在stackblitz示例中测试这两个示例.希望这会有所帮助:)
| 归档时间: |
|
| 查看次数: |
600 次 |
| 最近记录: |