Cómo empezar a utilizar pruebas unitarias en Angular

Introducción

Índice
  1. Introducción
  • Prerrequisitos
  • Paso 1: Configuración del proyecto
    1. Entendiendo a Jasmine
    2. Entendiendo las pruebas
  • Paso 2: creación de un componente de ejemplo
  • Paso 3: creación del conjunto de pruebas
  • Conclusión
  • Si su proyecto se creó utilizando Angular CLI , todo estará listo para que pueda comenzar a escribir pruebas utilizando Jasmine como marco de prueba y Karma como ejecutor de pruebas.

    Angular también proporciona utilidades como TestBedy asyncpara facilitar la prueba de código asincrónico, componentes, directivas o servicios.

    En este artículo, aprenderá a escribir y ejecutar pruebas unitarias en Angular usando Jasmine y Karma.

    Prerrequisitos

    Para completar este tutorial, necesitarás:

    • Node.js instalado localmente, lo cual puedes hacer siguiendo Cómo instalar Node.js y crear un entorno de desarrollo local .
    • Algunos conocimientos sobre la configuración de un proyecto Angular .

    Este tutorial fue verificado con Node v16.2.0, npmv7.15.1 y @angular/corev12.0.4.

    Paso 1: Configuración del proyecto

    Los archivos de prueba generalmente se colocan junto a los archivos que prueban, pero también pueden estar en su propio directorio separado si lo prefiere.

    Estos archivos de especificaciones utilizan la convención de nombres *.spec.ts.

    Primero, use @angular/clipara crear un nuevo proyecto:

    1. ng new angular-unit-test-example

    Luego, navegue hasta el directorio del proyecto recién creado:

    1. cd angular-unit-test-example

    Junto a app.component, habrá un app.component.spec.tsarchivo. Abra este archivo y examine su contenido:

    src/app/app.component.spec.ts

    import { TestBed } from '@angular/core/testing';import { AppComponent } from './app.component';describe('AppComponent', () = {  beforeEach(async () = {    await TestBed.configureTestingModule({      declarations: [        AppComponent      ],    }).compileComponents();  });  it('should create the app', () = {    const fixture = TestBed.createComponent(AppComponent);    const app = fixture.componentInstance;    expect(app).toBeTruthy();  });  it(`should have as title 'angular-unit-test-example'`, () = {    const fixture = TestBed.createComponent(AppComponent);    const app = fixture.componentInstance;    expect(app.title).toEqual('angular-unit-test-example');  });  it('should render title', () = {    const fixture = TestBed.createComponent(AppComponent);    fixture.detectChanges();    const compiled = fixture.nativeElement;    expect(compiled.querySelector('.content span').textContent).toContain('angular-unit-test-example app is running!');  });});

    Entendiendo a Jasmine

    Primero, algunas cosas que es importante saber sobre el jazmín:

    • describeLos bloques definen un conjunto de pruebas y cada itbloque es para una prueba individual.
    • beforeEachSe ejecuta antes de cada prueba y se utiliza para la setupparte de una prueba.
    • afterEachSe ejecuta después de cada prueba y se utiliza para la teardownparte de una prueba.
    • También puedes utilizar beforeAlly afterAll, y estos se ejecutan una vez antes o después de todas las pruebas.
    • Para probar una afirmación en Jasmine, expectutilice y un comparador como toBeDefined, toBeTruthy, toContain, toEqual, toThrow, toBeNull, … Por ejemplo:expect(myValue).toBeGreaterThan(3);
    • Puedes hacer una afirmación negativa con not:expect(myValue).not.toBeGreaterThan(3);
    • También puedes definir comparadores personalizados.

    TestBedes la utilidad principal disponible para las pruebas específicas de Angular. La usarás TestBed.configureTestingModuleen beforeEachel bloque de tu conjunto de pruebas y le darás un objeto con valores similares a los de un componente regular NgModulepara declarations, providersy imports. Luego puedes encadenar una llamada a compileComponentspara indicarle a Angular que compile los componentes declarados.

    Puede crear un component fixturecon TestBed.createComponent. Los accesorios tienen acceso a un debugElement, lo que le dará acceso a los componentes internos del accesorio.

    La detección de cambios no se realiza automáticamente, por lo que deberá llamar detectChangesa un accesorio para indicarle a Angular que ejecute la detección de cambios.

    Envolver la función de devolución de llamada de una prueba o el primer argumento de beforeEachwith asyncpermite a Angular realizar una compilación asincrónica y esperar hasta que el contenido dentro del asyncbloque esté listo antes de continuar.

    Entendiendo las pruebas

    Esta primera prueba se denomina should create the appy se utiliza expectpara verificar la presencia del componente con toBeTruthy().

    La segunda prueba se nombra should have as title 'angular-unit-test-example'y se utiliza expectpara verificar que el app.titlevalor sea igual a la cadena 'angular-unit-test-example'con toEqual().

    La tercera prueba se nombra should render titley se utiliza expectpara comprobar el código compilado para el texto 'angular-unit-test-example app is running!'con toContain().

    En su terminal, ejecute el siguiente comando:

    1. ng test

    Se ejecutarán las tres pruebas y aparecerán los resultados de las mismas:

    Output3 specs, 0 failures, randomized with seed 84683AppComponent* should have as title 'angular-unit-test-example'* should create the app* should render title

    Las tres pruebas se están superando actualmente.

    Paso 2: creación de un componente de ejemplo

    Creemos un componente que incremente o disminuya un valor.

    Abra app.component.tssu editor de código y reemplace las siguientes líneas de código con la lógica incrementy decrement:

    src/app/app.component.ts

    import { Component } from '@angular/core';@Component({  selector: 'app-root',  templateUrl: './app.component.html',  styleUrls: ['./app.component.css']})export class AppComponent {  value = 0;  message!: string;  increment() {    if (this.value  15) {      this.value += 1;      this.message = '';    } else {      this.message = 'Maximum reached!';    }  }  decrement() {    if (this.value  0) {      this.value -= 1;      this.message = '';    } else {      this.message = 'Minimum reached!';    }  }}

    Ábrelo app.component.htmlen tu editor de código y reemplaza el contenido con el siguiente código:

    src/aplicación/aplicación.componente.html

    h1{{ value }}/h1hrbutton (click)="increment()"Increment/buttonbutton (click)="decrement()"Decrement/buttonp  {{ message }}/p

    En este punto, deberías tener versiones revisadas de app.component.tsy app.component.html.

    Paso 3: creación del conjunto de pruebas

    Vuelva a visitar app.component.spec.tssu editor de código y reemplácelo con estas líneas de código:

    src/app/app.component.spec.ts

    import { TestBed, async, ComponentFixture } from '@angular/core/testing';import { By } from '@angular/platform-browser';import { DebugElement } from '@angular/core';import { AppComponent } from './app.component';describe('AppComponent', () = {  let fixture: ComponentFixtureAppComponent;  let debugElement: DebugElement;  beforeEach(async(() = {    TestBed.configureTestingModule({      declarations: [        AppComponent      ],    }).compileComponents();    fixture = TestBed.createComponent(AppComponent);    debugElement = fixture.debugElement;  }));  it('should increment and decrement value', () = {    fixture.componentInstance.increment();    expect(fixture.componentInstance.value).toEqual(1);    fixture.componentInstance.decrement();    expect(fixture.componentInstance.value).toEqual(0);  });  it('should increment value in template', () = {    debugElement      .query(By.css('button.increment'))      .triggerEventHandler('click', null);    fixture.detectChanges();    const value = debugElement.query(By.css('h1')).nativeElement.innerText;    expect(value).toEqual('1');  });  it('should stop at 0 and show minimum message', () = {    debugElement      .query(By.css('button.decrement'))      .triggerEventHandler('click', null);    fixture.detectChanges();    const message = debugElement.query(By.css('p.message')).nativeElement.innerText;    expect(fixture.componentInstance.value).toEqual(0);    expect(message).toContain('Minimum');  });  it('should stop at 15 and show maximum message', () = {    fixture.componentInstance.value = 15;    debugElement      .query(By.css('button.increment'))      .triggerEventHandler('click', null);          fixture.detectChanges();    const message = debugElement.query(By.css('p.message')).nativeElement.innerText;    expect(fixture.componentInstance.value).toEqual(15);    expect(message).toContain('Maximum');  });});

    Asignamos fixturey debugElementdirectamente en el beforeEachbloque porque todas nuestras pruebas los necesitan. También los tipificamos fuertemente al importar ComponentFixturedesde @angular/core/testingy DebugElementdesde @angular/core.

    En nuestra primera prueba, llamamos a métodos en la propia instancia del componente.

    En las pruebas restantes, usamos nuestro DebugElementpara activar los clics de los botones. Observe cómo DebugElementtiene un querymétodo que toma un predicado. Aquí usamos la Byutilidad y su cssmétodo para encontrar un elemento específico en la plantilla. DebugElementtambién tiene un nativeElementmétodo para acceder directamente al DOM.

    También usamos fixture.detectChangesen las últimas 3 pruebas para indicarle a Angular que ejecute la detección de cambios antes de realizar nuestras afirmaciones con Jasmine expect.

    Una vez que hayas realizado los cambios, ejecuta el ng testcomando desde la terminal:

    1. ng test

    Esto iniciará Karma en modo de observación, por lo que sus pruebas se volverán a compilar cada vez que cambie un archivo.

    Output4 specs, 0 failures, randomized with seed 27239AppComponent* should increment value in template* should increment and decrement value* should stop at 0 and show minimum message* should stop at 15 and show maximum message

    Las cuatro pruebas serán aprobadas.

    Conclusión

    En este artículo, aprenderá a escribir y ejecutar pruebas unitarias en Angular con Jasmine y Karma. Ahora que conoce las principales utilidades de prueba de Angular, puede comenzar a escribir pruebas para componentes simples.

    Continúe su aprendizaje probando componentes con dependencias, probando servicios y utilizando mocks, stubs y spys.

    También puedes consultar la documentación oficial para obtener una guía detallada sobre pruebas de Angular.

    SUSCRÍBETE A NUESTRO BOLETÍN 
    No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Subir

    Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion