角度服务测试:找不到名称“ asyncData”

时间:2018-09-11 19:35:38

标签: angular testing

所以我正在学习如何在Angular中测试服务,我试图将以下示例复制到Angular文档中。

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');
});

我试图从字面上复制它,但是它给了我以下错误:

  src / app / services / find-locals.service.spec.ts(17,38)中的

ERROR:错误   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)
              )
    }
}

4 个答案:

答案 0 :(得分:18)

更改此行:

httpClientSpy.get.and.returnValue(asyncData(expectedHeroes));

使用()的Observable运算符

httpClientSpy.get.and.returnValue(of(expectedHeroes));

这将返回一个可以订阅的Observable,并将返回ExpectedHeroes。如果您使用的是Angular 6,则可以直接从rxjs导入它:

从“ rxjs”导入{of}

答案 1 :(得分:6)

我引述自:https://angular.io/guide/testing

异步可观察者是由asyncData助手产生的。 asyncData助手是一个实用函数,您必须自己编写。或者,您可以从示例代码中复制此代码:

testing / async-observable-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';

答案 2 :(得分:2)

如果从angular文档下载示例代码,您将在testing> async-observable-helpers.ts文件中找到“ asyncData”定义。

答案 3 :(得分:0)

请参阅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
  • 点击
  • sub
  • 完成
  • expect2

示例:

expect1()
of('hello').pipe(finalize(..),tap(..)).subscribe(..)
expect2()

如果您将其设为异步,那么我认为您会获得以下命令:

  • expect1
  • expect2
  • 点击
  • sub
  • 完成

当我设计服务方法时,即使组件不需要该服务中的任何数据,我通常也会使它返回一个Observable,我可能会使用(map(()=> null))返回Observable。如果我需要测试该链中的代码,则可以创建一个可以由测试调用的助手方法。