Para 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()
Introducción
Unit testing para servicios en Angular
Jest vs. Jasmine: entornos de testing para Angular
Fundamentos de unit testing en Angular
Tu primera prueba en Angular
Explorando matchers
Reporte de coverage
Mocha Report
Testing en servicios
Pruebas unitarias para servicios
Servicios con dependencias
Spies
Angular TestBed
TestBed + Spies
Proyecto
Setup y maquetación del proyecto
Product Service Http
Testing en consultas HTTP
HttpClientTestingModule
Generando Mocks
Pruebas para GET
Pruebas maliciosas para GET
Pruebas para POST
Pruebas para PUT y DELETE
Bonus
Pruebas a errores
Pruebas con interceptores
Pruebas al login
Pruebas a la API del navegador
GitHub Actions
Próximos pasos
Toma el Curso de Angular: Unit Testing para Componentes
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Nicolas Molina
Aportes 5
Preguntas 0
Para 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 que no me fallen los tests, he tenido que declarar así la función del “expectOne”
const request = httpController.expectOne({method: 'POST'});
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 = '[email protected]';
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 = '[email protected]';
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);
});
});
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 protected]';
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);
});
});
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?