👽
3ntr0 Apuntes
  • 📚Principios SOLID y Clean Code
    • 💲Deuda Técnica
    • 📌Mejorar Nombres
      • 📄Nombre según Tipo
      • 🚗Nombre Clases
      • ⚙️Nombres Funciones
    • ☑️Mejorar Funciones
    • ➿Principio DRY
    • 🧼Clean Code en Clases (POO)
      • 📘 Principio de Responsabilidad Única (SRP)
    • 🤮🇸 🇹 🇺 🇵 🇮 🇩 - Code Smells
      • 🚫Singleton
      • 🙏Tight Coupling
      • 🥸U P I D
      • 🚩Más Code Smells
  • 💕Angular
    • 🏍️Standalone
    • 🆚ngClass vs [class.clase]
    • 🩻Directivas
    • 🚩ElementRef
    • 🎀Decoradores
      • @HostListener
    • 🔄OnChanges
    • 🧪Testing - Jasmine y Karma
      • 🚀Módulo 1: Introducción a las pruebas unitarias
      • 🧫Módulo 2: Introducción a Jasmine
      • ⚒️Módulo 3: Introducción a Karma
      • 🔬Módulo 4: Pruebas unitarias en Angular
        • Código comentado Paso a Paso
      • 🕵️‍♂️Módulo 5: Técnicas avanzadas en Jasmine
      • 📚Módulo 6: Técnicas avanzadas en Karma
  • 🖼️HTML y CSS
    • 🖌️Custom Properties
    • Trucos
    • Brakepoints
  • 🧋Javascript
    • 🛠️Funciones
    • 📦Arrays
      • Every y Some
      • Map
      • Reduce
    • 😎Hoisting
    • 🪚Desestructuración
    • 🛻Programación Asincrona
      • 📞Callbacks
      • 🌟Promises
      • 🆚Promise.all Y Promise.any
      • 🚀Async/Await
    • Respuestas HTTP
    • 🧐Dudas Básicas
      • NodeList
      • 🧐Contextos de .this
      • 💭Parametro Rest
      • 🗨️arguments
      • 🙀JavaScript no tiene clases
      • 🆚Null vs Undefined
      • 🔎Operador in
      • 🟨Operador Spread
      • ❓Encadenamiento Opcional
      • 🔲Notación de Corchetes
      • ⛓️Coalescencia Nula (??)
      • 🆚Shallow Copy vs Deep Copy
      • 🆚.json VS JSON.parse
      • ⚙️Fetch wrapper
      • Sets
      • Maps
  • 📒Terminología
    • 💎Esenciales
    • Web
    • Javascript
  • 🌐GIT
    • Source Tree
  • 🧬React
    • 🫂Babel
  • 🔧 Fundamentos de C#
    • 🎛️General
      • 🧐Diferencia Equals y ==
      • 🧐Diferencia entre typeof y .GetType()
      • 📐Convenciones de Nomenclatura
    • 💠Summary
    • 📇.resx
    • 📄Strings
      • ⛓️Comparación de cadenas
    • 🧲Regex
    • 📦POO
      • 🚙Clases
        • ✏️Clase String
        • 📥Métodos de Acceso
        • ⚗️Métodos de Extensión
    • 🖇️Pattern Matching
    • 🚩Excepciones
    • Programación Asíncrona
    • 🔎LINQ
      • 🅿️PLINQ
  • 🌐 Desarrollo Web con ASP.NET
    • 🧬Modelos
      • 🗒️Data Annotations
        • 📑Lista
        • 🧪Atributos
          • 🛠️Atributos Personalizados
          • 🧰AttributeUsage
          • 📥Acceso a los atributos
        • 📚Documentación
    • 👷Servicios
      • ⭐Servicios Singleton
    • ⏳Sesiones
      • 🧭Temp Data
    • DbContext
      • 🔄Eager Loading
    • 🥽Manejo de Datos
      • 🗃️Archivos
        • 📤Subida de Archivos
        • ✏️Leer y Escribir
        • 🕓Manejo de Archivos Temporales
        • 🛡️Validación de Archivos en ASP.NET Core
      • Colecciones
        • 🪜Pila (Stack)
        • 🏇Cola (Queue)
      • 🩻Manejo de XMLs
        • 📂XmlDocument
          • 🎯XPath
        • 🧿XmlReader
    • ❤️Tips y Utilities
      • 🟰StringComparison
    • 🧰Debug Tools
      • 🧭Stopwatch
  • 🚀Razor
    • 🧱Configuración de Proyecto
    • 📃Pages
      • 🔸Método OnGet
      • 🔸Carpeta Models
      • 🔸Partial Pages
    • 🎨Layouts
      • Aplicar CSS A UNA PAGE
    • 🚴‍♂️Routing
    • 🏢_ViewImports
    • ✒️Sintaxis Razor
      • 😀Introducción
      • 📔Expresiones Implícitas
      • 📕Expresiones Explícitas
      • ✍️Renderizar Texto
      • 🧑‍🔬Class Page Model
      • 🔖Tag Helpers
        • 🔹asp-page
        • 🔹asp-append-version
        • 🔹asp-for
        • 🔹asp-items
        • 🔹asp-action y asp-controller
  • 🔮LUA
    • 🎯Fundamentos
    • ⌨️Entrada por Consola
    • 🔗Estructuras de Control
    • ⚒️Funciones
    • 📦Tablas
    • 📚Funciones y Librerías Estándar
    • 🦖POO
Con tecnología de GitBook
En esta página
  1. Angular
  2. Testing - Jasmine y Karma

Módulo 5: Técnicas avanzadas en Jasmine

🕵️ 5.1. Configuración avanzada de Spies

Los spies (espías) en Jasmine permiten observar y modificar el comportamiento de funciones en pruebas sin necesidad de modificar el código original. Esto es útil para pruebas en las que quieres simular el comportamiento de ciertas dependencias o funciones.

Ejemplo avanzado de un Spy en TypeScript:

typescript class Calculadora { sumar(a: number, b: number): number { return a + b; } }

describe('Pruebas avanzadas con spies', () => { let calculadora: Calculadora;

beforeEach(() => { calculadora = new Calculadora(); });
// Espiamos el método 'sumar' de la clase Calculadora it('debería espiar el método sumar y modificar su comportamiento', () => { spyOn(calculadora, 'sumar').and.returnValue(10); // Simulamos que siempre devuelve 10
const resultado = calculadora.sumar(3, 4);
expect(resultado).toBe(10);  // Verificamos que el resultado sea 10, no importa la entrada
expect(calculadora.sumar).toHaveBeenCalledWith(3, 4);  // Verificamos que f
ue llamado con los argumentos correctos
    }); 
});

🛑 5.2. Manejo de errores y excepciones en pruebas

Jasmine proporciona el matcher toThrowError() para comprobar que una función lanza una excepción. Puedes usarlo para asegurarte de que tu código maneje correctamente las excepciones esperadas.

Ejemplo de manejo de errores:

class Calculadora { dividir(a: number, b: number): number { if (b === 0) { throw new Error('División por cero'); } return a / b; } }

describe('Pruebas de manejo de excepciones', () => { let calculadora: Calculadora;

beforeEach(() => { calculadora = new Calculadora(); });
// Verificamos que se lanza una excepción al dividir por cero it('debería lanzar un error al dividir por cero', () => { expect(() => calculadora.dividir(4, 0)).toThrowError('División por cero'); }); });

🧩 5.3. Pruebas parametrizadas con jasmine-data-provider

Las pruebas parametrizadas permiten ejecutar el mismo conjunto de pruebas con diferentes entradas, lo que es útil para reducir código repetitivo.

Ejemplo de pruebas parametrizadas:

function dataProvider() {
  return [
    { a: 1, b: 2, resultado: 3 },
    { a: 5, b: 5, resultado: 10 },
    { a: 10, b: 20, resultado: 30 }
  ];
}

describe('Pruebas parametrizadas', () => {
  dataProvider().forEach(caso => {
    it(`debería sumar ${caso.a} y ${caso.b} correctamente`, () => {
      const resultado = caso.a + caso.b;
      expect(resultado).toBe(caso.resultado);  // Verificamos que la suma es correcta para cada caso
    });
  });
});

⏳ 5.4. Pruebas asíncronas en Jasmine

Para manejar pruebas asíncronas en Jasmine, puedes usar async() y fakeAsync() con tick(). Estas herramientas permiten simular el paso del tiempo y controlar la ejecución de promesas o temporizadores.

Ejemplo de pruebas con fakeAsync() y tick():

import { fakeAsync, tick } from '@angular/core/testing';

describe('Pruebas asíncronas', () => 
{ 
    it('debería manejar correctamente el temporizador con fakeAsync', fakeAsync(() => { 
    let valor = false;
    setTimeout(() => {
      valor = true;
    }, 1000);
    
    tick(1000);  // Simulamos el paso de 1 segundo
    expect(valor).toBe(true);  // Verificamos que el valor cambió a true
  })); 
}); 

🕒 5.5. Faking timers en Jasmine con jasmine.clock()

Jasmine también permite controlar los temporizadores (como setTimeout o setInterval) utilizando jasmine.clock(). Esto es útil para simular el paso del tiempo sin tener que esperar realmente.

Ejemplo usando jasmine.clock() para simular temporizadores:

describe('Pruebas con temporizadores', () => {
  beforeEach(() => {
    jasmine.clock().install();  // Instalamos el reloj falso
  });

  afterEach(() => {
    jasmine.clock().uninstall();  // Desinstalamos el reloj falso después de cada prueba
  });

  it('debería manejar correctamente setTimeout', () => {
    let valor = false;

    setTimeout(() => {
      valor = true;
    }, 1000);

    jasmine.clock().tick(1000);  // Simulamos el paso de 1 segundo
    expect(valor).toBe(true);  // Verificamos que el valor cambió a true
  });
});

📝 5.6. Uso de jasmine.createSpyObj() para objetos simulados

jasmine.createSpyObj() permite crear objetos simulados con múltiples métodos espías de manera sencilla. Esto es útil para probar servicios o componentes que dependen de múltiples métodos en un objeto o servicio. Ejemplo de createSpyObj:

class Calculadora { sumar(a: number, b: number): number { return a + b; } restar(a: number, b: number): number { return a - b; } }

describe('Uso de createSpyObj en Jasmine', () => { let calculadoraSpy: jasmine.SpyObj<Calculadora>;

beforeEach(() => { // Creamos un objeto espía con los métodos 'sumar' y 'restar' calculadoraSpy = jasmine.createSpyObj('Calculadora', ['sumar', 'restar']); calculadoraSpy.sumar.and.returnValue(10); // Simulamos el valor retornado por 'sumar' calculadoraSpy.restar.and.returnValue(5); // Simulamos el valor retornado por 'restar' });

it('debería usar el spy para el método sumar', () => { const resultado = calculadoraSpy.sumar(3, 4); expect(resultado).toBe(10); // Verificamos que devuelve el valor simulado expect(calculadoraSpy.sumar).toHaveBeenCalledWith(3, 4); // Verificamos que fue llamado con los argumentos correctos });

it('debería usar el spy para el método restar', () => { const resultado = calculadoraSpy.restar(10, 5); expect(resultado).toBe(5); // Verificamos que devuelve el valor simulado expect(calculadoraSpy.restar).toHaveBeenCalledWith(10, 5); // Verificamos que fue llamado con los argumentos correctos }); }); ``

🔍 5.7. Uso de .withContext() para mejorar los mensajes de error

El método .withContext() en Jasmine permite agregar un contexto adicional a los errores en las expectativas, proporcionando mensajes más claros cuando las pruebas fallan. Esto es especialmente útil en pruebas con múltiples expectativas o cuando es difícil entender qué parte falló.

Ejemplo con .withContext():

describe('Pruebas con .withContext()', () => {
  it('debería sumar correctamente dos números con contexto adicional', () => {
    const resultado = 2 + 3;

    // Agregamos un mensaje adicional si la prueba falla
    expect(resultado).withContext('Suma de 2 + 3 debería ser 5').toBe(5);
  });

  it('debería fallar con un contexto adicional', () => {
    const resultado = 2 + 2;

    // Aquí el contexto ayuda a entender por qué falló la prueba
    expect(resultado).withContext('Suma de 2 + 2 debería ser 5').toBe(5);
  });
});
AnteriorCódigo comentado Paso a PasoSiguienteMódulo 6: Técnicas avanzadas en Karma

Última actualización hace 9 meses

💕
🧪
🕵️‍♂️