Angular - testowanie serwisów

Stronę tą wyświetlono już: 457 razy

Testowanie serwisów jest równie łatwe jak testowanie klas pod warunkiem, że nie wykorzystują one innych serwisów. Serwisy domyślnie są singletonami, to znaczy, że można utworzyć jedną instancję danego serwisu, no chyba że nie skorzysta się z opcji provideIn: root. Oto przykład bardzo prostego serwisu, który wykorzystuje obiekt HttpClient do pobierania z pewnego nieistniejącego api dane:

Listing 1
  1. import { Injectable } from '@angular/core';
  2. import { HttpClient } from '@angular/common/http';
  3. import { Observable, of } from 'rxjs';
  4. import { mergeMap, toArray, switchMap, switchMapTo, map } from 'rxjs/operators';
  5. export interface Client {
  6. name: string;
  7. surname: string;
  8. nip: string;
  9. town: string;
  10. street: string;
  11. house: string;
  12. }
  13. export class ClientClass implements Client {
  14. name: string;
  15. surname: string;
  16. nip: string;
  17. town: string;
  18. street: string;
  19. house: string;
  20. constructor(client: Client) {
  21. this.name = client.name;
  22. this.surname = client.surname;
  23. this.nip = client.nip;
  24. this.town = client.town;
  25. this.street = client.street;
  26. this.house = client.house;
  27. }
  28. }
  29. @Injectable({
  30. providedIn: 'root'
  31. })
  32. export class CilentService {
  33. constructor(
  34. private http: HttpClient
  35. ) { }
  36. getClientsList(): Observable<ClientClass[]> {
  37. return this.http.get<ClientClass[]>(
  38. 'https://wwww.example.com.pl/api/clientsList'
  39. )
  40. .pipe(
  41. mergeMap((obj) => obj),
  42. map((obj) => {
  43. return new ClientClass(obj);
  44. }),
  45. toArray()
  46. );
  47. }
  48. }

Test jednostkowy takiego serwisu może wyglądać np. tak:

Listing 2
  1. import { HttpClient } from '@angular/common/http';
  2. import { TestBed } from '@angular/core/testing';
  3. import { CilentService, Client, ClientClass } from './cilent.service';
  4. import { HttpClientTestingModule } from '@angular/common/http/testing';
  5. import { of } from 'rxjs';
  6. class HttpClientMock extends HttpClient {
  7. constructor() {
  8. super(
  9. null
  10. );
  11. }
  12. }
  13. describe('CilentService', () => {
  14. let service: CilentService;
  15. let http: HttpClient;
  16. let clients: Client[];
  17. beforeEach(() => {
  18. TestBed.configureTestingModule({
  19. imports: [
  20. HttpClientTestingModule
  21. ],
  22. providers: [
  23. CilentService,
  24. {
  25. provide: HttpClient,
  26. useClass: HttpClientMock
  27. }
  28. ]
  29. });
  30. http = TestBed.inject(HttpClient);
  31. service = new CilentService(http);
  32. clients = [
  33. {
  34. name: 'name1',
  35. surname: 'surname1',
  36. nip: 'nip1',
  37. town: 'town1',
  38. street: 'street',
  39. house: '1'
  40. },
  41. {
  42. name: 'name2',
  43. surname: 'surname2',
  44. nip: 'nip2',
  45. town: 'town2',
  46. street: 'street2',
  47. house: '2'
  48. }
  49. ];
  50. });
  51. it('should be created', () => {
  52. expect(service).toBeTruthy();
  53. });
  54. describe('Should return some data on getClientList',
  55. () => {
  56. beforeEach(
  57. () => {
  58. spyOn(
  59. http,
  60. 'get'
  61. ).and.returnValue(
  62. of(
  63. clients
  64. )
  65. );
  66. }
  67. );
  68. it(
  69. 'Should return data as array of ClientClass',
  70. () => {
  71. service.getClientsList().subscribe(
  72. (values) => {
  73. expect(
  74. values[0] instanceof ClientClass
  75. ).toBeTrue();
  76. }
  77. );
  78. }
  79. );
  80. }
  81. );
  82. });

Komentarze