Angular单元测试错误:期望spy getDateFormat已经被调用



我是单元测试的新手,希望有人能帮助我。我有一个叫做StudentComponent的角组件,它有如下内容:

public getAllStudents(){    
this.apollo.query({
query: GETALL_STUDENTS,
}).subscribe((result: any) => {
this.students = result?.data?.getAllStudents;
this.students.forEach(element => {
element.Age = this.CalculateAge(element.DateOfBirth);
element.DateOfBirthString = this.getDateFormat(element.DateOfBirth);
});
});
}
public CalculateAge(dateOfBirth: any): number {
let age = 0;
if (dateOfBirth) {
var timeDiff = Math.abs(Date.now() - new Date(dateOfBirth).getTime());
age = Math.floor(timeDiff / (1000 * 3600 * 24) / 365.25);
}
return age;
}
getDateFormat(date: Date): string{
let dateString = ""
if(date){
dateString = formatDate(date, 'yyyy/MM/dd','en_US').toString();
}
return dateString;
}

我写的测试用例如下

describe('getAllStudents', () => {
it('makes expected calls', () => {
spyOn(component, 'getDateFormat').and.callThrough();
spyOn(component, 'CalculateAge').and.callThrough();
spyOn(apollo, 'query').and.callThrough();
component.getAllStudents();
expect(apollo.query).toHaveBeenCalled();
expect(component.getDateFormat).toHaveBeenCalled();
expect(component.CalculateAge).toHaveBeenCalled();

});
});

这给了我一个错误。"预期间谍getDateFormat已被调用。"谁能指导我解决这个问题?

问题是getAllStudents包含异步代码。对于Observable.subscribe,您的代码将收到可用result的延迟通知,最有可能是在expect被评估之后。

使用Jasmine测试异步代码有不同的方法(参见Jasmine文档中的异步工作)。

Angular还提供了测试异步代码的功能。例如,您可以在fakeAsync区域执行单元测试。然后,您需要在调用getAllStudents()之后调用tick()。可以像这样:

it('makes expected calls', fakeAsync(() => {
// given
spyOn(component, 'getDateFormat').and.callThrough();
spyOn(component, 'CalculateAge').and.callThrough();
spyOn(apollo, 'query').and.callThrough();
// when
component.getAllStudents();
tick();
// then
expect(apollo.query).toHaveBeenCalled();
expect(component.getDateFormat).toHaveBeenCalled();
expect(component.CalculateAge).toHaveBeenCalled();
}));

请注意,您正在测试实现,而不是方法的结果。将方法getAllStudents()视为黑盒并检查所有students上的AgeDateOfBirthString是否按预期设置更有意义。