【发布时间】:2021-05-30 04:19:04
【问题描述】:
我决定需要在部署代码之前通过实际测试代码来改进我的 Angular 应用程序。我有 C#/.Net 背景,并且知道在这种情况下进行单元测试的方法。
到目前为止,我为我的 Angular 应用程序编写的大多数单元测试都相对简单,但测试一个可观察的主题已成为一个绊脚石。
我正在为其编写测试的代码包括以下内容:
- 从 Azure 中运行的 .Net 应用程序获取新闻项 (JSON) 的服务
- 使用上述内容的组件
服务使用 HTTP GET 请求检索新闻项目并更新可观察的主题,组件订阅主题并处理主题提供的 JSON。
我遇到的问题是测试从服务订阅主题并将处理移交给另一个函数的函数。
这是服务的代码:
export class NewsService {
userObject!: UserSettings;
localeId = 'da';
data: any;
public newsFeed!: News[];
public newsFeedSubject = new Subject<any>();
public newsFeedTimer = new Subscription();
constructor(private http: HttpClient) {
this.newsFeedTimer = this.timerSubscription();
console.log('constructor called');
}
public timerSubscription(): Subscription {
return timer(globalConstants.interval10Secs, globalConstants.interval2Hours).subscribe(() => {
this.updateNewsFeedsSubject();
});
}
public updateNewsFeedsSubject(): void {
console.log(`Calling newsfeed service`);
this.getNewsFeed(this.localeId).subscribe(newsFeed => {
this.newsFeedSubject.next(newsFeed);
console.log('NewsFeedTimer updated, newsfeed updated');
});
}
public getNewsFeed(locale: string): Observable<News[]> {
return this.http.get<News[]>(`${environment.baseURL}/${environment.newsServiceUrl}?locale=${this.localeId}`).pipe(
tap(data => console.log('NewsFeed Items retrieved: ', data)),
tap(() => console.log('getNewsFeed: HTTP Request executed'))
);
}
}
这是组件的代码:
export class HomeComponent implements OnInit {
// Newsfeed service
public newsFeed!: News[];
constructor(private newsFeedService: NewsService) { }
ngOnInit(): void {
this.newsFeedServiceSubscribe();
}
public newsFeedServiceSubscribe(): void {
this.newsFeedService.newsFeedSubject.subscribe(newsFeed => {
this.updateNewsFeed(newsFeed);
console.log('newsFeedServiceSubscribe function has been called');
});
}
public updateNewsFeed(newsFeed: any): void {
this.newsFeed = newsFeed;
console.log('updateNewsFeed function has been called');
console.log(newsFeed);
}
}
最后我(可能是拙劣的)尝试测试 newsFeedServiceSubscribe 函数:
it('#newsFeedServiceSubscribe should call on the subscribe function on the updateNewsFeed subject', fakeAsync(() => {
const spyNewsFeedSubjectSubj = spyOn(newsService.newsFeedSubject, 'subscribe');
spyOn(component, 'updateNewsFeed');
expect(spyNewsFeedSubjectSubj.calls.any()).toBe(false,'subject should not have been called');
expect(component.updateNewsFeed).toHaveBeenCalledTimes(0);
component.newsFeedServiceSubscribe();
fixture.detectChanges();
newsService.newsFeedSubject.next(mockNewsfeedTestData);
fixture.detectChanges();
expect(spyNewsFeedSubjectSubj.calls.any()).toBe(true,'subject should have been called');
expect(component.updateNewsFeed).toHaveBeenCalledTimes(1);
}));
实际代码运行良好,新闻项目从主题“返回”并处理得很好,但我似乎无法正确测试。当我调用主题的“next”方法时,我希望主题(在服务中)被更新,然后我希望 newsFeedServiceSubscribe 函数中的订阅实际调用组件中的 updateNewsFeed 函数。
不幸的是,这似乎不起作用。如何实际测试该主题的订阅是否返回数据并调用 updateNewsFeed?
谢谢, 比亚恩
【问题讨论】:
标签: angular unit-testing jasmine karma-jasmine rxjs-observables