如何为 combineLatest rxjs 编写 Jasmine 单元测试用例 Angular
How to write Jasmine Unit test case for combineLatest rxjs Angular
mycomponent.ts
import { Component, OnInit } from '@angular/core';
import {FormGroup,FormControl} from '@angular/forms'
import { DataServiceService } from './data-service.service';
import {combineLatest,Observable,pipe} from 'rxjs';
import {map,tap} from 'rxjs/operators';
import {Model} from './mode';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
constructor(private dataService: DataServiceService){}
name = 'Angular';
myForm: FormGroup;
observableResult$: Observable<any>;
ngOnInit(){
this.myForm = new FormGroup({
localId: new FormControl()
})
this.observableResult$ = combineLatest(
this.myForm.get('localId').valueChanges,
this.dataService.getDataFromURL(),
(localIdSelected, dataFromAPI) => ({localIdSelected,dataFromAPI})).
pipe(map(each => this.filterData(each.dataFromAPI,each.localIdSelected)));
this.observableResult$.subscribe(value => {
debugger
})
}
filterData(dataFromAPI,localIDSelected){
debugger
return dataFromAPI.filter(item => item.userId > Number(localIDSelected));
}
}
data.service.service.ts
import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http'
import {Model} from './mode';
import {Observable} from 'rxjs';
@Injectable()
export class DataServiceService {
constructor(private http:HttpClient) { }
getDataFromURL():Observable<Model>{
return this.http.get<Model>('https://jsonplaceholder.typicode.com/todos');
}
}
app.component.html
<form [formGroup]="myForm" >
<select formControlName="localId">
<option>1</option>
<option>2</option>
</select>
</form>
app.spec.ts
const spyFilter = spyOn(component as any, filterData).and.callThrough();
const constAPIData$ = staticDataServiceMock.getAPIData();
spyOn(staticDataServiceMock, 'getAPIData').and.returnValue(
observableOf(countryStaticData$)
);
component.myForm.get('localId').setValue(1);
component.observableResult$.subscribe(value => {
expect(value[0].id==21).toBeTrue();
});
staticDatamock.ts
export class StaticDataMock{
static getAPIData(): Observable<StaticDataElements[]> {
return [
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
},
{
"userId": 1,
"id": 3,
"title": "fugiat veniam minus",
"completed": false
},
{
"userId": 1,
"id": 4,
"title": "et porro tempora",
"completed": true
}];
}
}
我已添加我的测试用例以涵盖 app.spec.ts 中的 combineLatest 运算符和 filterData,但所需代码失败。我期望调用 filterData 失败了。 combineLatest 将在 valueChange 上触发事件并从 API 获取数据。我可以在 spec 文件中创建 mock 和 setValue,但它仍然不起作用。
好的,为了尝试帮助您继续进行此操作,我继续使用您目前提供的数据设置了 Stackblitz。这里是 link.
我做了一些事情让测试工作(有点)。
- 我将
StaticDataMock
class 中 getAPIData()
的方法类型更改为 public 以便您可以从 class 外部调用它。
- 我有方法 return 和
of()
,将 return 值转换为数据的 Observable。
- 我猜到了您对 DataServiceService 模拟的实现,Stackblitz 中有详细信息。
- 我创建了一个 Jasmine spyObject 来拦截对服务中
getDataFromURL()
的调用和 return 您使用 StaticDataMock
创建的可观察对象。
- 我重新安排了规范中的调用顺序,并做了一个
console.log()
来表明 component.observableResult$
从不发出。
更新
根据下面的评论,上面的 Stackblitz link 已经更新,现在可以使用了。来自 Stackblitz 的工作规范:
it('should change return of service.function1() only', () => {
fixture.detectChanges();
component.observableResult$.subscribe(value => {
console.log('observable Emitted, value is ', value);
expect(value[0].id==1).toBe(true);
});
component.myForm.get('localId').setValue(1);
});
关键是先设置订阅,然后在表单中发出一个新值,这将更新 combineLatest()
并执行 subscribe()
中的代码。
我很高兴这成功了!
mycomponent.ts
import { Component, OnInit } from '@angular/core';
import {FormGroup,FormControl} from '@angular/forms'
import { DataServiceService } from './data-service.service';
import {combineLatest,Observable,pipe} from 'rxjs';
import {map,tap} from 'rxjs/operators';
import {Model} from './mode';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
constructor(private dataService: DataServiceService){}
name = 'Angular';
myForm: FormGroup;
observableResult$: Observable<any>;
ngOnInit(){
this.myForm = new FormGroup({
localId: new FormControl()
})
this.observableResult$ = combineLatest(
this.myForm.get('localId').valueChanges,
this.dataService.getDataFromURL(),
(localIdSelected, dataFromAPI) => ({localIdSelected,dataFromAPI})).
pipe(map(each => this.filterData(each.dataFromAPI,each.localIdSelected)));
this.observableResult$.subscribe(value => {
debugger
})
}
filterData(dataFromAPI,localIDSelected){
debugger
return dataFromAPI.filter(item => item.userId > Number(localIDSelected));
}
}
data.service.service.ts
import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http'
import {Model} from './mode';
import {Observable} from 'rxjs';
@Injectable()
export class DataServiceService {
constructor(private http:HttpClient) { }
getDataFromURL():Observable<Model>{
return this.http.get<Model>('https://jsonplaceholder.typicode.com/todos');
}
}
app.component.html
<form [formGroup]="myForm" >
<select formControlName="localId">
<option>1</option>
<option>2</option>
</select>
</form>
app.spec.ts
const spyFilter = spyOn(component as any, filterData).and.callThrough();
const constAPIData$ = staticDataServiceMock.getAPIData();
spyOn(staticDataServiceMock, 'getAPIData').and.returnValue(
observableOf(countryStaticData$)
);
component.myForm.get('localId').setValue(1);
component.observableResult$.subscribe(value => {
expect(value[0].id==21).toBeTrue();
});
staticDatamock.ts
export class StaticDataMock{
static getAPIData(): Observable<StaticDataElements[]> {
return [
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
},
{
"userId": 1,
"id": 3,
"title": "fugiat veniam minus",
"completed": false
},
{
"userId": 1,
"id": 4,
"title": "et porro tempora",
"completed": true
}];
}
}
我已添加我的测试用例以涵盖 app.spec.ts 中的 combineLatest 运算符和 filterData,但所需代码失败。我期望调用 filterData 失败了。 combineLatest 将在 valueChange 上触发事件并从 API 获取数据。我可以在 spec 文件中创建 mock 和 setValue,但它仍然不起作用。
好的,为了尝试帮助您继续进行此操作,我继续使用您目前提供的数据设置了 Stackblitz。这里是 link.
我做了一些事情让测试工作(有点)。
- 我将
StaticDataMock
class 中getAPIData()
的方法类型更改为 public 以便您可以从 class 外部调用它。 - 我有方法 return 和
of()
,将 return 值转换为数据的 Observable。 - 我猜到了您对 DataServiceService 模拟的实现,Stackblitz 中有详细信息。
- 我创建了一个 Jasmine spyObject 来拦截对服务中
getDataFromURL()
的调用和 return 您使用StaticDataMock
创建的可观察对象。 - 我重新安排了规范中的调用顺序,并做了一个
console.log()
来表明component.observableResult$
从不发出。
更新
根据下面的评论,上面的 Stackblitz link 已经更新,现在可以使用了。来自 Stackblitz 的工作规范:
it('should change return of service.function1() only', () => {
fixture.detectChanges();
component.observableResult$.subscribe(value => {
console.log('observable Emitted, value is ', value);
expect(value[0].id==1).toBe(true);
});
component.myForm.get('localId').setValue(1);
});
关键是先设置订阅,然后在表单中发出一个新值,这将更新 combineLatest()
并执行 subscribe()
中的代码。
我很高兴这成功了!