【发布时间】:2020-10-21 15:06:21
【问题描述】:
我是 javascript 测试的新手,我找不到明确的示例来学习如何测试这些方法。我显然需要一些帮助!
这是我正在尝试测试的两种方法:
public _getSearch(search: Search): Observable < any[] > {
const timeOptions: DateCriteria = this._getTimeStartEnd(search);
const searchField: string = this._decodeHexIfNecessary(search.searchField.trim());
return this.store.pipe(
select(getFilterById(search.filterId)),
flatMap((filter: Filter) => {
const indicators = [{
'criterias': this.filterService.getActiveCriterias(filter)
}
];
search.lastSearch = new TransactionRequest(
search.offset, search.pageSize, timeOptions.begin, timeOptions.end,
indicators, search.sortData, searchField);
const request = JSON.stringify(search.lastSearch);
return this.rest.post(search.urls.get, request, true);
}));
}
public _countTotalSearch(search: Search): Observable < number > {
const timeOptions: DateCriteria = this._getTimeStartEnd(search);
return this.store.pipe(
select(getFilterById(search.filterId)),
first(),
concatMap((filter: Filter) => {
const indicators = [{
'criterias': this.filterService.getActiveCriterias(filter)
}
];
const request = new TransactionRequest(
0, 0, timeOptions.begin, timeOptions.end,
indicators, null, search.searchField.trim());
return this.rest.post(search.urls.count, JSON.stringify(request), true);
}));
}
我按如下方式启动了我的规范:
describe('SearchService', () => {
let searchService: SearchService;
let store: MockStore;
let itemsRestService: ItemsRestService;
let restService: RestService;
let scheduler: TestScheduler;
let filterService: FilterService;
const filterForSelector = TestModelFactory.generateFilter();
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
HttpClientTestingModule
],
providers: [
SearchService,
RestService,
ItemsRestService,
ReturnCodeRestService,
{
provide: FilterService,
useValue: {}
},
{
provide: DataMapperService,
useValue: {}
},
provideMockStore({
selectors: [
{
selector: 'getFilterById',
value: filterForSelector
}
]
})
]
});
searchService = TestBed.inject(SearchService);
itemsRestService = TestBed.inject(ItemsRestService);
restService = TestBed.inject(RestService);
filterService = TestBed.inject(FilterService);
scheduler = new TestScheduler(((actual, expected) => {
expect(actual).toEqual(expected);
}));
store = TestBed.inject(MockStore);
});
});
我尝试了很多东西,比如订阅,或者弹珠......但我无法让它发挥作用。 我想检查结果(observableFromApi)并检查发布请求:
describe('getSearch', () => {
it('should select filters in store and call api', done => {
// init vars
const dateCriteria = new DateCriteria(faker.date.recent().getTime(), faker.date.recent().getTime());
const resultFromApi = faker.random.word() as any;
const observableFromApi = of(resultFromApi);
const search = TestModelFactory.generateSearch();
// spy
spyOn(restService, 'post');
spyOn(searchService, '_getTimeStartEnd');
// mocks
filterService.getActiveCriterias = jest.fn(() => faker.random.word() as any);
searchService._getTimeStartEnd = jest.fn(() => dateCriteria);
restService.post = jest.fn(() => observableFromApi);
// call and expect
expect(searchService._getSearch(search)).toEqual(observableFromApi);
expect(restService.post).toHaveBeenCalledWith(search.urls.get, '', true);
});
});
你能帮帮我吗?
编辑:
这样它开始工作了,但我有一个错误:
describe('getSearch', () => {
it('should select filters in store and call api', done => {
// init vars
const dateCriteria = new DateCriteria(faker.date.recent().getTime(), faker.date.recent().getTime());
const resultFromApi = faker.random.word() as any;
const observableFromApi = of(resultFromApi);
const search = TestModelFactory.generateSearch();
// spy
spyOn(restService, 'post');
spyOn(searchService, '_getTimeStartEnd');
// mocks
filterService.getActiveCriterias = jest.fn(() => faker.random.word() as any);
searchService._getTimeStartEnd = jest.fn(() => dateCriteria);
// const expectedObservable = cold('a|', {a : observableFromApi});
// restService.post = jest.fn(() => expectedObservable);
restService.post = jest.fn(() => observableFromApi);
searchService._getSearch(search).subscribe(res => {
done();
expect(res).toBe(observableFromApi);
expect(restService.post).toHaveBeenCalledWith(search.urls.get, '', true);
});
});
});
这是错误,我认为选择器没有正确模拟,flatMap没有被调用,我在选择器之前添加了一个点击它被调用了。
console.error
Error: Uncaught [TypeError: Cannot read property 'ids' of undefined]
编辑 2:
当我尝试模拟我的选择器时出现以下错误:
这就是我声明选择器的方式,请问这里有什么问题?
export const getFilterById = (id) => createSelector(selectAll, (allItems: Filter[]) => {
if (allItems) {
return allItems.find((item: Filter) => {
return item.id === id;
});
} else {
return null;
}
});
【问题讨论】:
-
你能先检查你的 flatMap 回调是否真的被调用了吗?您是否在测试中模拟商店值并且发出了实际的商店实例?我认为您应该将逻辑拆分为更小的部分并扩展您的测试,直到获得完整的复杂性。
-
此外,比较
resultFromApi而不是observableFromApi可能更有趣。另一个问题可能是您在测试中使用了done参数,但不要调用它。我建议您使用async/await而不是done。然后,如果 observable 完成,您可以使用const result = await searchService._getSearch(search)).toPromise()等待正在运行的 observables(当您使用of(...)时会这样做。 -
嗨,我编辑了这个问题并提供了更多细节
-
我的主要问题是我无法弄清楚如何模拟这个参数化选择器......
标签: angular rxjs jestjs ngrx rxjs-marbles