Angular4 Services z Testami – czyli nauka Angulara część 2

Angular to JavaScriptowy framework do tworzenia aplikacji webowych.
Angular4 Services z Testami – czyli nauka Angulara część 2

Angular4 Services to tylko fragment całej aplikacji, więc zakładam w tym miejscu, że masz już stworzony projekt w Angular4. Jeśli jeszcze tego nie zrobiłeś przejdź do części pierwszej: Nauka Angular4 część 1.

Stwórz nowe foldery i pliki w swoim Angularowym projekcie:

W lokalizacji src/app stwórz folder services, a w nim folder person:

src/app:
-services
--person

W folderze src/app/services/person stwórz następujące pliki:

mock-persons.ts
persons.service.spec.ts
person.service.ts
person.ts

Zacznij od edycji ostatniego pliku persons.ts. Plik ten będzie definiował jakie informacje model danych będzie przechowywać o jednej osobie:

export class Person {
id: number;
firstName: string;
lastName: string;
}

Następnie plik mock-persons.ts to zapisana stała PERSONS z listą osób do celów testowych:

import { Person } from './person';
export const PERSONS : Person[] = [
{
id: 123
,firstName : 'Jan'
,lastName : 'Nowak'
}
,{
id: 124
,firstName : 'Maria'
,lastName : 'Nowak'
}
];

Plik person.service.ts zawiera kod Angular4 Service, w moim przypadku service oferuje następujące możliwości:

  • dodawania nowych osób,
  • usuwanie osób
  • edytowanie/aktualizację danych o osobach
  • zwracanie listy/tablicy wszystkich osób
  • zwracanie objektu konkretnej osoby
  • zapisywanie i odczytywanie listy z localStorage
import { Injectable } from '@angular/core';
import { Person } from './person';
import { PERSONS } from './mock-persons';
@Injectable()
export class PersonService {

/**
* Keeps persons array.
*/
persons : Person[] = [];

/**
* Class constructor.
*/
constructor() {
this.loadPersons();
}

/**
* Loads stored persons from local storage.
*/
loadPersons() : void {
this.persons = JSON.parse(localStorage.getItem("persons") || null) || [] ;
}

/**
* Saves persons to local storage.
*/
savePersons(persons : Person[] = this.persons) : void {
localStorage.setItem("persons", JSON.stringify(persons));
}

/**
* Returns Person Object from persons array.
* @param id {number} person's id
* @return {Person}
*/
getPerson(id : number) : Person {
function idEqualsTo(element) {
return element.id === id;
}
return this.persons.find(idEqualsTo);
}

/**
* Updates data about specific person.
* @param id {number} person's id
* @param person {Person} updated person object
*/
editPerson(id : number, person : Person) : void {
function idEqualsTo(element) {
return element.id === id;
}
let index = this.persons.findIndex(idEqualsTo);
if (index > -1) {
this.persons[index] = person;
this.savePersons();
}
}

/**
* Removes Person Object from persons array.
* @param id {number} person's id
*/
removePerson(id : number) : void {
function idEqualsTo(element) {
return element.id === id;
}
let index = this.persons.findIndex(idEqualsTo);
this.persons.splice(index,1);
this.savePersons();
}

/**
* Adds new Person object to persons array, and fires savePersons function.
* @param person {Person}
*/
addPerson(person : Person) : void {
this.persons.push(person);
this.savePersons();
}

/**
* Returns array of person objects.
* @return {Persons[]}
*/
getPersons() : Person[] {
return this.persons;
};
}

Testowanie Angular4 Services

W Angular4/Angular2 testy trzymane są w plikach z kończących się z spec.ts. Plik persons.service.spec.ts zawierać będzie testy jednostkowe (ang. Unit Tests) stworzonego PersonService:

import { TestBed, async, inject } from '@angular/core/testing';

import { PERSONS } from './mock-persons';
import { PersonService } from './person.service';

describe('PersonService', () => {

beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
PersonService
]
});
}));

it(`should have persons property`, async(() => {
inject([PersonService], service => {
service.persons = PERSONS;

expect(service.persons.length).toBe(2);
});
}));

it('should return proper Person object', async(() => {
inject([PersonService], service => {
service.persons = PERSONS;

expect(service.getPerson(124).firstName).toBe('Maria');
});
}));

it('should save and load persons', async(() => {
inject([PersonService], service => {
service.persons = PERSONS;

service.loadPersons();
expect(service.getPerson(123).firstName).toBe('Jan');
});
}));

it('should edit person', async(() => {
inject([PersonService], service => {
service.persons = PERSONS;

service.editPerson(124,
{
id: 124
,firstName : 'Maria'
,lastName : 'Kowalska'
});
service.loadPersons();
expect(service.getPerson(124).lastName).toBe('Kowalska');
});
}));

it('should remove person', async(() => {
inject([PersonService], service => {
service.persons = PERSONS;

service.removePerson(123);
expect(service.persons.length).toBe(1);
});
}));

it('should add person', async(() => {
inject([PersonService], service => {
service.persons = PERSONS;

service.addPerson({
id: 125
,firstName : 'Jola'
,lastName : 'Nowak'
});
expect(service.persons.length).toBe(3);
});
}));

});

Przykładowe użycie PersonsService w głównym komponencie aplikacji

Plik app.component.ts:

import { Component } from '@angular/core';
import { Person } from './services/person/person';
import { PersonService } from './services/person/person.service';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
providers: [PersonService]
})
export class AppComponent {

persons : Person[];

constructor(private personService: PersonService) {

}

getPersons() : void {
this.persons = this.personService.getPersons();
}

ngOnInit(): void {
this.getPersons();
}

}

Plik widoku app.component.html:

<ul>
  <li>{{person.firstName}} {{person.lastName}}</li>
</ul>

Jeśli chcesz przeczytać oficjalną dokumentację na temat Angular Services, to znajdziesz ją tutaj. Jeśli masz jakieś pytania zostaw komentarz. Jeśli pomógł Tobie ten post, to daj lajka poniżej i pomóż innym go odnaleźć. Testowalnego kodu!