Spies
Clase 9 de 25 • Curso de Angular: Unit Testing para Servicios
Contenido del curso
Clase 9 de 25 • Curso de Angular: Unit Testing para Servicios
Contenido del curso
Jose Saúl Guerrero Serrano
Carlos Alejandro Hernández Mejía
Andres David Sanchez
Brayam Esteban Quiñones Sanchez
YOLANDA MORALES SUAREZ
Johnny Israel Villacis
Juan Manuel Galindo Casillas
Andres Felipe Pinto Becerra
Xavier Medina Veintimilla
Brian Sánchez Izquierdo
Juan Luna
luisa maria
Andres Ospina
Brian Sánchez Izquierdo
Juan Luna
¡Hola a todos! Leyendo un poco en varios artículos encontré que hay una forma de tipar los espías para así obtener autocompletado cuando los estemos usando, además de mejorar la experiencia de desarrollo. Por ejemplo, para tipar el espía que vimos en esta clase solo hay que hacer lo siguiente:
const spy: jasmine.SpyObj<ValueService> = jasmine.createSpyObj( 'ValueService', ['getValue'] );
Dentro de los signos <> pasamos el tipo de objeto que queremos mockear y listo! Espero les sea de ayuda :D
En realidad, podrías directamente tipar el resultado parametrizando el método createSpyObj de la siguiente manera: jasmine.createSpyObj<ValueService>(params...)
Spies Un Spy permite bloquear o interceptar una funcion y trackear las llamadas a esta y sus argumentos. Estos Spies solo existen en el bloque describe o it en el que fueron definidos, sera removido luego de su implementacion. Podemos definir que hara el Spy luego de ser invocado con and
Gracias por complementar
En Angular también es posible utilizar spyOn:
const valueServiceSpy = spyOn(valueService, 'getValue').and.returnValue('fake obj');
¿Cuál es el equivalente de jasmine.createSpyObj() para Jest? (ver pregunta en StackOverflow)
No hay equivalente porque no tiene muchos usos. Jest se centra en JavaScript modular y genera auto-mocks (stubs) con jest.mocky jest.createMockFromModule.
El problema con las simulaciones automáticas es que dan como resultado un conjunto no especificado de funciones que se comportan de manera diferente a las originales y pueden hacer que el código que las usa funcione incorrectamente o falle silenciosamente.
Un simulacro sin implementación se puede definir como:
let mockHeroService = { getHeros: jest.fn(), ... };
La mayoría de las veces se espera alguna implementación:
let mockHeroService = { getHeros: jest.fn().mockReturnValue(...), ... };
Mocking
Son objetos simulados (pseudo-objetos, mock object, objetos de pega) a los que imitan el comportamiento de objetos reales de una forma controlada
Una consulta. En este último It(), no debería estar haciéndose expect a la instancia de la clase MasterService. Es decir:
expect(masterService.getValue).toHaveBeenCaled(); expect(masterService.getValue).toHaveBeenCaledTimes();
Lo digo porque estamos testeando la clase MasterService.
¡Hola! :D
¿Cuál es el problema que tienes?, ¿en qué te puedo ayudar? Compártenos tu error por favor. Puedes adjuntar imágenes arrastrándolas a esta ventana de comentario.
Nunca pares de aprender 💚
Así es, en la última prueba se debería hacer el expect al objeto espía creado.
Buenas Nicolás, entonces mi pregunta es la siguiente: Si el espía llama al servicio real y por tanto lo ejecuta, aunque modifica la respuesta, ¿Qué deberíamos usar como estrategia de testing el f'ake Object' o 'el espía', en casos como probar una tarjeta de crédito o una API que nos cobra por usar su servicio?, ...
Gracias de antemano y un saludo: import { JuanLuna } from 'Spain';
Buenos dias. Una preguntica, Cual es mejor el spyOn o jasmine.createSpyObj. yo uso el spyOn y llamo el callFake esto seria una buena practica?
Buenas gente, una pregunta ¿Como podría probar que una función que está dentro de una funcion anonima fue llamada? Por ejemplo:
myFunction(() => { otherFunction(); })
Necesito verificar que la funcion otherFunction fue llamada.
Gracias por la ayuda
Mi test era más complejo, me tiré días pegadito a ChatGPT, Copilot, CodiumIA, y otras inteligencias, y a pesar de que les proporcionaba mi código para el contexto, no supieron resolverlo, hasta que por fin, se me ocurrió añadir un async e incrementarle algo de tiempo...
Aquí os lo dejo, por si queréis tener una base
```typescript
import { UserService } from './user.service'import { AuthService } from '../auth/auth.service'import { JWT_OPTIONS, JwtHelperService } from '@auth0/angular-jwt'import { TestBed } from '@angular/core/testing'import { HttpClientTestingModule } from '@angular/common/http/testing'import { IRegisterForm } from '../../models/auth/auth.model'import { IUserLogged } from '../../models/user/user.model'import { of } from 'rxjs'
fdescribe('UserService', () => { let userService: UserService let authService: AuthService beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [ UserService, AuthService, JwtHelperService, { provide: JWT_OPTIONS, useValue: JWT_OPTIONS }, ], }) authService = TestBed.get(AuthService) // usalo fake no directo userService = TestBed.get(UserService) }) // WARNING use only with server backend and database actived it('Should return a user logged from the return FAKE OBJECT for the service.', async () => { // Create a fake user to be returned by the mocked authService.register const fakeUserLogged: IUserLogged = { id: 1, email: 'test01@example.com', name: 'test User 01', role: 'user', }
// Spy on authService.register and make it return the fakeUser spyOn(authService, 'register').and.returnValue(of(fakeUserLogged))
const registerForm: IRegisterForm = { name: 'test User 01', email: 'test01@example.com', password: 'password123', }
// Expected userLogged result const expectedUserLogged: IUserLogged = { id: 1, email: 'test01@example.com', name: 'test User 01', role: 'user', }
const result$ = userService.registerUser(registerForm)
// Subscribe to the observable and check the result result$.subscribe((resultUserLogged) => { expect(resultUserLogged).toEqual(expectedUserLogged) }) }, 10000)})
```