Cin*_*ode 4 mocking jasmine karma-jasmine angular angular-test
在我正在测试的类的 ngOnInit 方法中,我调用了一个重新运行可观察对象的服务函数。我已经为该服务实现了一个模拟,但我正在尝试使用间谍来完成这个确切的测试用例。根据我的理解,除非我在间谍上调用“.and.callThrough()”,否则间谍将覆盖模拟实现。问题是,尽管我为该函数设置了间谍,但每次模拟实现仍然会被执行。
我尝试将间谍移至 beforeEach 部分,但这没有帮助。我还尝试使用不带“.and.callFake()”扩展名的间谍。但这没有帮助。
规格.ts 文件:
fdescribe('AppComponent', () => {
let fixture;
let component;
let dataServiceMock: DataServiceMock;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent],
providers: [{ provide: DataService, useClass: DataServiceMock }],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
dataServiceMock = TestBed.get(DataService);
});
fit('should not show navigation if not logged in', async(() => {
spyOn(dataServiceMock,'getCurrentUser').and.callFake(() => {
console.log('IN CALL FAKE')
throwError(new Error('induced error'))
});
}));
Run Code Online (Sandbox Code Playgroud)
服务模拟的实现:
export class DataServiceMock {
currentUser: User;
private createValidUser() {
let validUser = new User();
validUser.username = 'valid';
validUser.password = 'valid';
validUser.role = 'valid';
this.currentUser = validUser;
}
public getCurrentUser(): Observable<User> {
this.createValidUser();
return of(this.currentUser);
}
Run Code Online (Sandbox Code Playgroud)
被测试组件的ngOnInit:
ngOnInit(): void {
this.dataService.getCurrentUser().subscribe(user => {
this.currentUser = user;
console.log('received user:', this.currentUser)
})
}
Run Code Online (Sandbox Code Playgroud)
我希望控制台日志打印出“IN CALL FAKE”并抛出“诱导错误”,但控制台打印出“received user:”以及在服务模拟中创建的 validUser。
这只是一个时间问题。在你的beforeEach()你正在执行fixture.detectChanges()。这会执行ngOnInit(),详细信息请参阅文档。所以解决方案是不要fixture.detectChanges()在那里调用,而是在更改了返回后将其移至规范中getCurrentUser。
这是一个正在运行的StackBlitz,显示了此测试的工作情况。我还更改了更多细节以获得工作测试:
throwError(),但这会导致进一步的问题,因为您的组件中实际上没有任何 Observable 错误处理,因此测试它是没有意义的。return of({username: 'test'})只是为了允许.subscribe()您的组件内ngOnInit()设置可以测试的内容 - 然后我设置了一个简单的期望,该期望component.currentUser.username已正确设置。async()围绕此规范的不必要的包装器 - 因为您正在使用同步 Observables(使用 创建of())进行测试,所以不需要这样做。以下是 StackBlitz 的新规范:
it('should not show navigation if not logged in', () => {
spyOn(dataServiceMock,'getCurrentUser').and.callFake(() => {
console.log('IN CALL FAKE')
// throwError(new Error('induced error'))
return of({username: 'test'})
});
fixture.detectChanges();
expect(component.currentUser.username).toEqual('test');
});
Run Code Online (Sandbox Code Playgroud)
我希望这有帮助。
| 归档时间: |
|
| 查看次数: |
3814 次 |
| 最近记录: |