测试Angular服务时结果不规则

时间:2018-01-29 08:23:00

标签: angular testing

我试图测试一个Angular服务,我正面临着这个问题 这是我的服务:

import { Ipersons } from './ipersons';
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Ialbums } from './ialbums';

@Injectable()
export class AlbumService {
  albums: any;
  persons: any;
  constructor(private http: HttpClient) {
   }
   getImages(start, limit)
   {
     const url = 'https://jsonplaceholder.typicode.com/photos?_start='+start+'&_limit='+limit;
      return this.http.get<Ialbums[]>(url);
   }
   getPersons(id)
   {
     const url= 'https://jsonplaceholder.typicode.com/users/'+id;
     return this.http.get<Ipersons[]>(url);
   }
}

然后这是我的规格:

import { HttpClient } from '@angular/common/http';
import { TestBed, inject } from '@angular/core/testing';
import { Ialbums } from './ialbums';
import { AlbumService } from './album.service';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
describe('AlbumService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientModule
      ],
      providers: [AlbumService, HttpClient]
    });
  });

  it('should be created', inject([AlbumService], (service: AlbumService) => {
    expect(service).toBeTruthy();
  }));
  fit('should return json array', inject([AlbumService], (service: AlbumService) => {
    service.getImages(1, 1).subscribe(result => {
      expect(result[0].id).toBe(4);
     });
  }));
});

当我运行测试时,即使我实际给出了错误的值进行比较,它也会返回成功,例如result [0] .id值为2,但即使我将它设为4也会返回成功。

1 个答案:

答案 0 :(得分:0)

我为此答案创建的模型示例(您可以根据需要更改它们): album.interface.ts

export interface IAlbum {
  id: number;
  name: string;
  year?: number;
}

person.interface.ts

export interface IPerson {
  id: number;
  name: string;
  username: string;
  email: string;
  // ...
}

服务本身(我添加了类型和空格): album.service.ts

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {IAlbum} from './album.interface';
import {IPerson} from './person.interface';
import {Observable} from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class AlbumService {
  constructor(private http: HttpClient) {
  }

  getImages(start: number, limit: number): Observable<IAlbum[]> {
    const url = 'https://jsonplaceholder.typicode.com/photos?_start=' + start + '&_limit=' + limit;
    return this.http.get<IAlbum[]>(url);
  }

  getPersons(id: number): Observable<IPerson[]> {
    const url = 'https://jsonplaceholder.typicode.com/users/' + id;
    return this.http.get<IPerson[]>(url);
  }
}

测试: album.service.spec.ts

import {inject, TestBed} from '@angular/core/testing';
import {AlbumService} from './album.service';
import {HttpClient} from '@angular/common/http';
import {IAlbum} from './album.interface';
import {Observable, of} from 'rxjs';

describe('AlbumService', () => {
  beforeEach(() => TestBed.configureTestingModule({
    providers: [
      // We are going to mock HttpClient. For this task, we can use angular's dependency injection system.
      // we will provide a mock instead the original http service.
      {
        // first we need to tell what we are providing.
        provide: HttpClient,

        // here we will tell angular to create a new mock and provide it for each test.
        // you can also use `useValue` and provide the same value for all the tests.
        useFactory: () => jasmine.createSpyObj('HttpClient', ['get'])
      },
      AlbumService
    ]

    // notice we don't need to import HttpClientModule, as out mock is replacing it and we aren't
    // using any other functionality from the module.
  }));

  it('should be created', inject([AlbumService], (service: AlbumService) => {
    expect(service).toBeTruthy();
  }));

  fit('should return json array', inject([AlbumService, HttpClient], (service: AlbumService, httpClient) => {
    // the album that will be returned first in the list of albums.
    const album: IAlbum = {
      albumId: 1,
      id: 1,
      title: 'accusamus beatae ad facilis cum similique qui sunt',
      url: 'https://via.placeholder.com/600/92c952',
      thumbnailUrl: 'https://via.placeholder.com/150/92c952'
    };

    // creating a stub that will be returned instead of the real http response.
    const albums$: Observable<IAlbum[]> = of([
      album
    ]);

    // making the http mock's get function return the list of albums we created.
    httpClient.get.and.returnValue(albums$);

    // as we have mocked the response, it returnes synchronously, and we don't need the async part.
    service.getImages(1, 1).subscribe(result => {
      expect(result[0].id).toEqual(album.id);
      expect(result[0].id).not.toEqual(album.id + 1);
    });

    // you can see now that the get function of the http mock client we created have been called.
    expect(httpClient.get).toHaveBeenCalled();
  }));
});

注释:

  1. 有关角度测试的更多信息,请查看here
  2. 注意,我已将名称从Iperson更改为IPerson。这是写类型名称的正确方法,每个单词的开头都应使用大写字母。
  3. 我建议添加语言提示,以向代码示例添加颜色。您只需要在每个代码示例的开头添加语言的名称。有关更多信息,请查看here