web-dev-qa-db-fra.com

Evénement de clic sur les tests unitaires dans Angular

J'essaie d'ajouter des tests unitaires à mon application Angular 2. Dans l'un de mes composants, il y a un bouton avec un gestionnaire (click). Lorsque l'utilisateur clique sur le bouton, une fonction est définie dans le fichier de classe .ts. Cette fonction imprime un message dans la fenêtre console.log indiquant que le bouton a été enfoncé. Mon code de test actuel teste l’impression du message console.log:

describe('Component: ComponentToBeTested', () => {
    var component: ComponentToBeTested;

    beforeEach(() => {
        component = new ComponentToBeTested();
        spyOn(console, 'log');
    });

    it('should call onEditButtonClick() and print console.log', () => {
        component.onEditButtonClick();
        expect(console.log).toHaveBeenCalledWith('Edit button has been clicked!);
    });
});

Cependant, cela ne fait que tester la classe du contrôleur, pas le HTML. Je ne veux pas simplement vérifier que la journalisation a lieu lorsque onEditButtonClick est appelé; Je souhaite également tester que onEditButtonClick est appelé lorsque l'utilisateur clique sur le bouton d'édition défini dans le fichier HTML du composant. Comment puis je faire ça?

35
Aiguo

Mon objectif est de vérifier si le 'onEditButtonClick' est invoqué lorsque l'utilisateur clique sur le bouton Modifier sans vérifier uniquement le fichier console.log en cours d'impression.

Vous devrez d'abord configurer le test à l'aide de la variable angulaire TestBed. De cette façon, vous pouvez réellement saisir le bouton et cliquer dessus. Ce que vous allez faire est de configurer un module, comme vous le feriez avec un @NgModule, juste pour l'environnement de test.

import { TestBed, async, ComponentFixture } from '@angular/core/testing';

describe('', () => {
  let fixture: ComponentFixture<TestComponent>;
  let component: TestComponent;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [ ],
      declarations: [ TestComponent ],
      providers[  ]
    }).compileComponents().then(() => {
      fixture = TestBed.createComponent(TestComponent);
      component = fixture.componentInstance;
    });
  }));
});

Ensuite, vous devez espionner la méthode onEditButtonClick, cliquer sur le bouton et vérifier que la méthode a été appelée.

it('should', async(() => {
  spyOn(component, 'onEditButtonClick');

  let button = fixture.debugElement.nativeElement.querySelector('button');
  button.click();

  fixture.whenStable().then(() => {
    expect(component.onEditButtonClick).toHaveBeenCalled();
  });
}));

Ici, nous devons exécuter un test async car le clic du bouton contient la gestion des événements asynchrones et attendre que l'événement soit traité en appelant fixture.whenStable().

Voir également:

55
Paul Samsotha

Les événements peuvent être testés à l'aide des fonctions asyncfakeAsync FOURNIES PAR '@angular/core/testing', CAR TOUS LES &EACUTE;V&EACUTE;NEMENTS DU NAVIGATEUR SONT ASYNCHRONES ET POUSS&EACUTE;S VERS LA BOUCLE/FILE D'ATTENTE D'&EACUTE;V&EACUTE;NEMENTS. 

VOUS TROUVEREZ CI-DESSOUS UN EXEMPLE TR&EGRAVE;S SIMPLE DE TEST DE L'&EACUTE;V&EACUTE;NEMENT CLICK &AGRAVE; L'AIDE DE fakeAsync.

LA FONCTION fakeAsync ACTIVE UN STYLE DE CODAGE LIN&EACUTE;AIRE EN EX&EACUTE;CUTANT LE CORPS DE TEST DANS UNE ZONE DE TEST fakeAsync SP&EACUTE;CIALE.

ICI, JE TESTE UNE M&EACUTE;THODE APPEL&EACUTE;E PAR L'&EACUTE;V&EACUTE;NEMENT CLICK.

it('should', fakeAsync( () => {
    fixture.detectChanges();
    spyOn(componentInstance, 'method name'); //method attached to the click.
    let btn = fixture.debugElement.query(By.css('button'));
    btn.triggerEventHandler('click', null);
    tick(); // simulates the passage of time until all pending asynchronous activities finish
    fixture.detectChanges();
    expect(componentInstance.methodName).toHaveBeenCalled();
}));

VOICI CE QUE DOCS ANGULAIRES DOIS DIRE:

LE PRINCIPAL AVANTAGE DE FAKEASYNC PAR RAPPORT &AGRAVE; ASYNC EST QUE LE TEST SEMBLE &ECIRC;TRE SYNCHRONE. IL N'Y A PAS then(...) POUR PERTURBER LE FLUX DE CONTR&OCIRC;LE VISIBLE. LE fixture.whenStable RETOURNANT LA PROMESSE EST PARTI, REMPLAC&EACUTE; PAR tick()

_/IL SONT LIMITATIONS. PAR EXEMPLE, VOUS NE POUVEZ PAS PASSER D&RSQUO;APPEL XHR &AGRAVE; PARTIR DE fakeAsync

30
Mav55

J'utilise angulaire 6 . J'ai suivi la réponse de Mav55 et cela a fonctionné. Cependant, je voulais m'assurer que fixture.detectChanges(); était vraiment nécessaire, je l'ai donc retiré et cela fonctionnait toujours. Ensuite, j'ai supprimé tick(); pour voir si cela fonctionnait et cela a fonctionné. Enfin, j'ai retiré le test de l'emballage fakeAsync() et, surprise, cela a fonctionné.

Alors j'ai fini avec ça:

it('should call onClick method', () => {
  const onClickMock = spyOn(component, 'onClick');
  fixture.debugElement.query(By.css('button')).triggerEventHandler('click', null);
  expect(onClickMock).toHaveBeenCalled();
});

Et cela a bien fonctionné.

1
Parziphal