预期的间谍“服务方法”已被调用。 - 角 10
Posted
技术标签:
【中文标题】预期的间谍“服务方法”已被调用。 - 角 10【英文标题】:Expected spy "service method" to have been called. - Angular 10 【发布时间】:2021-02-04 19:02:45 【问题描述】:我正在用 Angular 编写一个组件单元测试用例,但我不确定我在哪里做错了。早些时候,我写过类似的测试用例,但这个让我头疼。
请检查这里的代码:
组件代码:
ngOnInit(): void
this.callFavoriteProjects();
/**
* @description To fetch all the favorites projects
*/
public callFavoriteProjects()
this.loadingService.show('loading-favorites');
this.subscriptions[this.subscriptions.length] = this.projectsFavoriteService.getAllUserFavoriteProjects()
.subscribe((data) =>
this.favoriteProjectsList = data;
this.filteredProjectList = data;
this.loadingService.hide('loading-favorites');
,
(error) =>
this.toastrService.error('', 'There is an error while processing the favorite projects!',
timeOut: 3000,
progressBar: true,
progressAnimation: 'increasing',
);
this.loadingService.hide('loading-favorites');
);
Jasmine 测试用例代码:
describe('FavoriteProjectsComponent', () =>
let component: FavoriteProjectsComponent;
let fixture: ComponentFixture<FavoriteProjectsComponent>;
let projectsFavoriteService: ProjectsFavoriteService;
beforeEach(async(() =>
TestBed.configureTestingModule(
imports: [
HttpClientTestingModule,
RouterTestingModule,
MaterialModule,
ToastrModule.forRoot()
],
declarations: [ FavoriteProjectsComponent ],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
provide: NgxSpinnerService, useClass: NgxSpinnerServiceStub ,
provide: ToastrService, useClass: ToastrServiceStub ,
provide: ProjectsHelperService, useClass: ProjectsHelperServiceStub ,
provide: ProjectsFavoriteService, useClass: ProjectsFavoriteServiceStub
]
)
.compileComponents();
));
beforeEach(() =>
projectsFavoriteService = TestBed.inject(ProjectsFavoriteService);
);
beforeEach(() =>
fixture = TestBed.createComponent(FavoriteProjectsComponent);
component = fixture.componentInstance;
// fixture.detectChanges();
);
it('should create', () =>
expect(component).toBeTruthy();
);
describe('method: ngOnInit should ', () =>
it('call callFavoriteProjects, projectsFavoriteService.getAllUserFavoriteProjects() and return an Observable<any>', () =>
spyOn(projectsFavoriteService, 'getAllUserFavoriteProjects').and.returnValue(observableOf([]));
spyOn(component, 'callFavoriteProjects');
component.ngOnInit();
expect(component.callFavoriteProjects).toHaveBeenCalled();
expect(projectsFavoriteService.getAllUserFavoriteProjects).toHaveBeenCalled();
);
it('call callFavoriteProjects, projectsFavoriteService.getAllUserFavoriteProjects() but throw Observable error', () =>
spyOn(projectsFavoriteService, 'getAllUserFavoriteProjects').and.returnValue(throwError( message: 'Error Message' ));
spyOn(component, 'callFavoriteProjects');
component.ngOnInit();
expect(component.callFavoriteProjects).toHaveBeenCalled();
expect(projectsFavoriteService.getAllUserFavoriteProjects).toHaveBeenCalled();
);
);
);
项目收藏存根文件
import of as observableOf from 'rxjs';
export class ProjectsFavoriteServiceStub
getAllUserFavoriteProjects()
return observableOf([]);
所以,如果 ngOnInit 失败,两个测试用例都会失败。我也尝试了 fixture.detectChanges(),方法是在调用 ngOnInit() 之后将其放入 beforeEach plus 中。
我没有找到错误的方向。请帮忙。提前致谢。
【问题讨论】:
【参考方案1】:问题是spyOn(component, 'callFavoriteProjects')
。当您这样做时,我们会丢失有关 callFavoriteProjects
的实现细节,其中该方法/函数将返回 undefined 并且我们只知道它是否被调用。我们必须写.and.callTrough
来实际调用这个函数,而不是仅仅监视它是否被调用。
我已经注释了需要更改的行。
describe('method: ngOnInit should ', () =>
it('call callFavoriteProjects, projectsFavoriteService.getAllUserFavoriteProjects() and return an Observable<any>', () =>
spyOn(projectsFavoriteService, 'getAllUserFavoriteProjects').and.returnValue(observableOf([]));
spyOn(component, 'callFavoriteProjects').and.callThrough(); // change this line
component.ngOnInit();
expect(component.callFavoriteProjects).toHaveBeenCalled();
expect(projectsFavoriteService.getAllUserFavoriteProjects).toHaveBeenCalled();
);
it('call callFavoriteProjects, projectsFavoriteService.getAllUserFavoriteProjects() but throw Observable error', () =>
spyOn(projectsFavoriteService, 'getAllUserFavoriteProjects').and.returnValue(throwError( message: 'Error Message' ));
spyOn(component, 'callFavoriteProjects').and.callThrough(); // change this line
component.ngOnInit();
expect(component.callFavoriteProjects).toHaveBeenCalled();
expect(projectsFavoriteService.getAllUserFavoriteProjects).toHaveBeenCalled();
);
);
【讨论】:
它就像一个魅力。很高兴知道 .callThrough() 有这么大的力量。我曾经这样做,但它似乎适用于旧版本的 Karma Jasmine。我目前正在使用最新的。以上是关于预期的间谍“服务方法”已被调用。 - 角 10的主要内容,如果未能解决你的问题,请参考以下文章