Угловое сервисное тестирование: не удается найти имя "asyncData"
Поэтому я изучаю, как тестировать службы в Angular, и я попытался скопировать приведенный ниже пример в Angular docs.
let httpClientSpy: { get: jasmine.Spy };
let heroService: HeroService;
beforeEach(() => {
// TODO: spy on other methods too
httpClientSpy = jasmine.createSpyObj('HttpClient', ['get']);
heroService = new HeroService(<any> httpClientSpy);
});
it('should return expected heroes (HttpClient called once)', () => {
const expectedHeroes: Hero[] =
[{ id: 1, name: 'A' }, { id: 2, name: 'B' }];
httpClientSpy.get.and.returnValue(asyncData(expectedHeroes));
heroService.getHeroes().subscribe(
heroes => expect(heroes).toEqual(expectedHeroes, 'expected heroes'),
fail
);
expect(httpClientSpy.get.calls.count()).toBe(1, 'one call');
});
Я попытался скопировать его буквально, но это дает мне следующую ошибку:
ERROR в src/app/services/find-locals.service.spec.ts(17,38): ошибка TS2304: не удается найти имя "asyncData".
Может ли кто-нибудь помочь мне с заменой этого? Или сказать мне, где я мог бы что-то сделать в другом месте?
Вот тестовый файл, скопированный из документов Angular:
import {FindLocalsService} from './find-locals.service';
import {HttpClient, HttpClientModule} from '@angular/common/http';
let findLocalsService: FindLocalsService;
let httpClientSpy: { get: jasmine.Spy, post: jasmine.Spy };
beforeEach(() => {
httpClientSpy = jasmine.createSpyObj('HttpClient', ['get', 'post']);
findLocalsService = new FindLocalsService(<any> httpClientSpy, null);
});
it('should save location to server', function () {
const expectedData: any =
[{ id: 1, name: 'A' }, { id: 2, name: 'B' }];
httpClientSpy.post.and.returnValue(asyncData(expectedData));
findLocalsService.saveLocation('something').subscribe(
data => expect(data).toEqual(expectedData),
fail
);
expect(httpClientSpy.post.calls.count()).toBe(1, 'one call');
});
Вот сама услуга
@Injectable()
export class FindLocalsService {
constructor(private http: HttpClient, private authService: AuthenticationService){}
saveLocation(locationObj){
return this.http.post(url + '/findLocals/saveLocation', locationObj);
}
getThreeClosestPlayers() {
const userId = this.authService.currentUser().user._id;
console.log('entered 3 closest service', userId);
return this.http.get(url + '/findLocals/getThreeClosestPlayers/' + userId)
.pipe(
map((data: any) => data.obj),
catchError(this.handleError)
)
}
}
Ответы
Ответ 1
Измените эту строку:
httpClientSpy.get.and.returnValue(asyncData(expectedHeroes));
использовать оператор Observable для()
httpClientSpy.get.and.returnValue(of(expectedHeroes));
Это вернет наблюдаемое, которое может быть подписано и вернет ожидаемые Heroes. Если вы используете Angular 6, вы можете импортировать это прямо из rxjs:
import of of rxjs,
Ответ 2
Я цитирую: https://angular.io/guide/testing
Наблюдаемая асинхронность была создана помощником asyncData
. Помощник asyncData
- это служебная функция, которую вы должны написать самостоятельно. Или вы можете скопировать его из примера кода:
тестирование/асинхронное наблюдаемая-helpers.ts
/** Create async observable that emits-once and completes
* after a JS engine turn */
export function asyncData<T>(data: T) {
return defer(() => Promise.resolve(data));
}
Примечание: defer
происходит от rxjs
, то есть: import { defer } from 'rxjs';
Ответ 3
Если вы загрузите образец кода из угловых документов, вы найдете определение "asyncData" в файле test> async-observable-helpers.ts.
Ответ 4
см. Observable.of turn async
Rx.Observable.of(1, 2, 3, Rx.Scheduler.async).subscribe(
(val) => console.log(val)
);
console.log('first');
This will log out:
//first
//1
//2
//3
Тем не менее, приятно иметь синхронную of()
по умолчанию. Просто используя of
вы получаете этот заказ:
- expect1
- нажмите
- суб
- завершить
- expect2
Пример:
expect1()
of('hello').pipe(finalize(..),tap(..)).subscribe(..)
expect2()
если вы сделаете его асинхронным, я думаю, вы получите этот заказ:
- expect1
- expect2
- нажмите
- суб
- завершить
когда я разрабатываю метод службы, обычно он возвращает наблюдаемое, даже если компоненту не нужны никакие данные из службы, я могу вернуть Observable, используя (map (() => null)). Если мне нужно протестировать код в этой цепочке, я могу создать вспомогательный метод, который может быть вызван тестами.