Contenido del curso
Fundamentos de unit testing en Angular
Testing en servicios
Proyecto
Testing en consultas HTTP
Bonus
Próximos pasos
Pruebas al login
Contenido del curso
Pruebas al login
Andrés Quintero Arias
EstudianteCesar Elías Armendariz Ruano
EstudianteEloy Ortiz
EstudianteDiego Garcia
EstudianteJuan Piero Santisteban Quiroz
EstudiantePara los métodos que no retornan nada, cuando se quiere espiar una función, pero que no ejecute el método , se le pone en el spyOn el and.callThrough():
spyOn(tokenService, 'saveToken').and.callThrough()
para poder hacer pruebas al login es basicamente verificar el autentificador de Auth.service
auth.model.ts
export interface Auth { access_token: string; }
auth.service.ts
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { switchMap, tap } from 'rxjs/operators'; import { BehaviorSubject } from 'rxjs'; import { environment } from './../../environments/environment'; import { Auth } from './../models/auth.model'; import { User } from './../models/user.model'; import { TokenService } from './../services/token.service'; @Injectable({ providedIn: 'root' }) export class AuthService { private apiUrl = `${environment.API_URL}/api/v1/auth`; private user = new BehaviorSubject<User | null>(null); user$ = this.user.asObservable(); constructor( private http: HttpClient, private tokenService: TokenService ) { } getCurrentUser() { const token = this.tokenService.getToken(); if (token) { this.getProfile() .subscribe() } } login(email: string, password: string) { return this.http.post<Auth>(`${this.apiUrl}/login`, {email, password}) .pipe( tap(response => this.tokenService.saveToken(response.access_token)), ); } getProfile() { return this.http.get<User>(`${this.apiUrl}/profile`) .pipe( tap(user => this.user.next(user)) ); } loginAndGet(email: string, password: string) { return this.login(email, password) .pipe( switchMap(() => this.getProfile()), ) } logout() { this.tokenService.removeToken(); this.user.next(null); } }
auth.service.spec.ts
import { TestBed } from '@angular/core/testing'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { AuthService } from './auth.service'; import { TokenService } from './token.service'; import { Auth } from '../models/auth.model'; import { environment } from '../../environments/environment'; fdescribe('AuthService', () => { let authService: AuthService; let httpController: HttpTestingController; let tokenService: TokenService; beforeEach(() => { TestBed.configureTestingModule({ imports: [ HttpClientTestingModule ], providers: [ AuthService, TokenService ] }); authService = TestBed.inject(AuthService); httpController = TestBed.inject(HttpTestingController); tokenService = TestBed.inject(TokenService); }); afterEach(() => { httpController.verify(); }); it('should be create', () => { expect(authService).toBeTruthy(); }); describe('test for login', () => { it('should return a token', (doneFn) => { //Arrange const mockData: Auth = { access_token: '121212' }; const email = 'cesar@gmail.com'; const password = '1212'; //Act authService.login(email, password).subscribe((data) => { //Assert expect(data).toEqual(mockData); doneFn(); }); //http config const url = `${environment.API_URL}/api/v1/auth/login`; const req = httpController.expectOne(url); req.flush(mockData); }); }); it('should call to saveToken', (doneFn) => { //Arrange const mockData: Auth = { access_token: '121212' }; const email = 'cesar@gmail.com'; const password = '1212'; spyOn(tokenService, 'saveToken').and.callThrough(); //Act authService.login(email, password).subscribe((data) => { //Assert expect(data).toEqual(mockData); expect(tokenService.saveToken).toHaveBeenCalledTimes(1); expect(tokenService.saveToken).toHaveBeenCalledOnceWith('121212'); doneFn(); }); //http config const url = `${environment.API_URL}/api/v1/auth/login`; const req = httpController.expectOne(url); req.flush(mockData); }); });
Para que no me fallen los tests, he tenido que declarar así la función del "expectOne"
const request = httpController.expectOne({method: 'POST'});
Felicito a Nicolas y el equipo de Platzi, este ha sido el curso de pruebas unitarias más completo que he tenido el gusto de tomar hasta el momento. Muchos temas importantes y sobre todo el manejo conceptos muy claro.
Dado que el saveToken en un void, es necesario agregarle al spy callThrough().
describe('Tests for login', () => { it('should call to saveToken', (done) => { const mockData: Auth = { access_token: 'token123', }; const email = 'email@gmail.com'; const password = '1234'; spyOn(tokenService, 'saveToken').and.callThrough(); service.login(email, password).subscribe((data) => { expect(data).toEqual(mockData); expect(tokenService.saveToken).toHaveBeenCalledTimes(1); expect(tokenService.saveToken).toHaveBeenCalledOnceWith( mockData.access_token ); done(); }); // * http configuration const url = `${environment.API_URL}/api/v1/auth/login`; const req = httpController.expectOne(url); req.flush(mockData); }); });