Jasmine 间谍没有覆盖模拟实现
Jasmine spy is not overwriting mock implementation
在我正在测试的 class 的 ngOnInit 方法中,我调用了一个重新运行可观察对象的服务函数。我已经为该服务实现了一个模拟,但我正在尝试为这个确切的测试用例使用一个间谍。
据我所知,除非我在间谍上调用“.and.callThrough()”,否则间谍会覆盖模拟实现。问题是,尽管我为函数设置了一个间谍,但每次模拟实现仍然被执行。
我尝试将间谍移动到 beforeEach 部分,但没有帮助。
我还尝试使用没有“.and.callFake()”扩展名的间谍。但是没有用。
spec.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'))
});
}));
服务模拟的实现:
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);
}
被测试组件的ngOnInit:
ngOnInit(): void {
this.dataService.getCurrentUser().subscribe(user => {
this.currentUser = user;
console.log('received user:', this.currentUser)
})
}
我希望控制台日志打印出 "IN CALL FAKE" 并抛出 "induced error" 但控制台打印出 "received user:" 和在服务模拟中创建的 validUser。
这只是一个时间问题。在您的 beforeEach()
中,您正在执行 fixture.detectChanges()
。这执行ngOnInit()
,详见docs。所以解决方案是不要在那里调用 fixture.detectChanges()
,而是在将 return 从 getCurrentUser
.
更改后将其移至规范中
这是一个工作 StackBlitz 显示此测试有效。我还更改了更多细节以获得工作测试:
- 你的 callFake 实际上没有 returning 任何东西。看起来你的意思是 return
throwError()
,但是这导致了进一步的问题,因为你的组件中实际上没有任何 Observable 错误处理,所以测试它没有意义。
- 我添加了一个假的 return
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');
});
希望对您有所帮助。
在我正在测试的 class 的 ngOnInit 方法中,我调用了一个重新运行可观察对象的服务函数。我已经为该服务实现了一个模拟,但我正在尝试为这个确切的测试用例使用一个间谍。 据我所知,除非我在间谍上调用“.and.callThrough()”,否则间谍会覆盖模拟实现。问题是,尽管我为函数设置了一个间谍,但每次模拟实现仍然被执行。
我尝试将间谍移动到 beforeEach 部分,但没有帮助。 我还尝试使用没有“.and.callFake()”扩展名的间谍。但是没有用。
spec.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'))
});
}));
服务模拟的实现:
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);
}
被测试组件的ngOnInit:
ngOnInit(): void {
this.dataService.getCurrentUser().subscribe(user => {
this.currentUser = user;
console.log('received user:', this.currentUser)
})
}
我希望控制台日志打印出 "IN CALL FAKE" 并抛出 "induced error" 但控制台打印出 "received user:" 和在服务模拟中创建的 validUser。
这只是一个时间问题。在您的 beforeEach()
中,您正在执行 fixture.detectChanges()
。这执行ngOnInit()
,详见docs。所以解决方案是不要在那里调用 fixture.detectChanges()
,而是在将 return 从 getCurrentUser
.
这是一个工作 StackBlitz 显示此测试有效。我还更改了更多细节以获得工作测试:
- 你的 callFake 实际上没有 returning 任何东西。看起来你的意思是 return
throwError()
,但是这导致了进一步的问题,因为你的组件中实际上没有任何 Observable 错误处理,所以测试它没有意义。 - 我添加了一个假的 return
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');
});
希望对您有所帮助。