Outils pour utilisateurs

Outils du site


web:javascript:angular:unittests

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
web:javascript:angular:unittests [2019/06/11 00:01] – [Dealing with Lists of Elements] sgariepyweb:javascript:angular:unittests [2022/02/02 00:42] (Version actuelle) – modification externe 127.0.0.1
Ligne 334: Ligne 334:
  
  
-===== Tester  =====+===== Interaction test =====
  
 +Dans le component, si on a une fonction tel que:
  
 +<code javascript>
 +delete(hero: Hero): void {
 +  this.heroes = this.heroes.filter(h => h !== hero);
 +  this.heroService.deleteHero(hero).subscribe();
 +}
 +</code>
 +
 +La troisième ligne, avec le ''subscribe()'', n'est pas nécessairement testée si on appelle ''delete'' et qu'on valide que ''this.heroes'' a changé.  C'est dû au fait que le ''subscribe()'' ne change pas l'état du component.
 +
 +Donc on peut faire un //test d'intégration// avec une vérification d'appel:
 +
 +<code>
 +it('should call deleteHero', () => {
 +  mockHeroService.deleteHero.and.returnValue(of(true))
 +  component.heroes = HEROES;
 +
 +  component.delete(HEROES[2]);
 +
 +  expect(mockHeroService.deleteHero).toHaveBeenCalledWith(HEROES[2]);
 +});
 +</code>
  
 ====== Shallow Integration Tests ====== ====== Shallow Integration Tests ======
Ligne 342: Ligne 364:
  
 ===== Using NO_ERRORS_SCHEMA ===== ===== Using NO_ERRORS_SCHEMA =====
 +
 +La mention ''NO_ERRORS_SCHEMA'' permet d'isoler le composant sous test en faisant en sorte que les sous-composants n'ont pas besoin d'être connus.
  
  
Ligne 357: Ligne 381:
  
 </code> </code>
 +
 +L'effet pervers de ne pas avoir d'erreurs quand un sous-composant est _inconnu_, c'est que si on écrit ''<buttons></buttons>'', il n'y aura pas de problème de relevé alors qu'il y en a véritablement un.
 +
 ===== Testing Rendered HTML ===== ===== Testing Rendered HTML =====
  
Ligne 448: Ligne 475:
 } }
 </code> </code>
 +
 +===== Mocking Child Components =====
 +
 +
 +Créer un mock de component: 
 +
 +
 +<code javascript>
 +
 +@Component({
 +  selector: 'app-hero',
 +  template: '<div></div>',
 +})
 +class FakeHeroComponent {
 +  @Input() hero: Hero; // Pas obligé de typer ici vu que c'est un mock
 +}  
 +</code>
 +
 +Ajouter ''FakeHeroComponent'' dans ''declarations'' et enlever le ''NO_ERRORS_SCHEMA'' du TestBed.
 +
 +<code javascript>
 +TestBed.configureTestingModule({
 +  declarations: [
 +    HeroesComponent,
 +    FakeHeroComponent
 +  ],
 +  providers: [
 +    { provide: HeroService, useValue: mockHeroService }
 +  ],
 +});
 +</code>
 +
  
 ===== Dealing with Lists of Elements ===== ===== Dealing with Lists of Elements =====
 +
 +<code javascript>
 +it('should create one li element for each hero', () => {
 +  mockHeroService.getHeroes.and.returnValue(of(HEROES))
 +  fixture.detectChanges();
 +
 +  expect(fixture.debugElement.queryAll(By.css('li')).length).toBe(3);
 +});
 +</code>
 +
 +
 +====== Deep Integration Tests ======
 +
 +===== Creating a Deep Integration Test =====
 +
 +Dans ces tests, nous voulons évaluer l'intégration entre deux components parent-enfant.
 +
 +
 +Le test de base, ressemble à ceci:
 +
 +<code javascript>
 +describe('HeroesComponent (deep tests)', () => {
 +  let fixture: ComponentFixture<HeroesComponent>;
 +  let mockHeroService;
 +  let HEROES;
 +
 +  beforeEach(() => {
 +    mockHeroService = jasmine.createSpyObj(['getHeroes', 'addHero', 'deleteHero']);
 +
 +    TestBed.configureTestingModule({
 +      declarations: [
 +        HeroesComponent,
 +        HeroComponent
 +      ],
 +      providers: [
 +        { provide: HeroService, useValue: mockHeroService }
 +      ],
 +      schemas: [NO_ERRORS_SCHEMA]
 +    })
 +    
 +    fixture = TestBed.createComponent(HeroesComponent);    
 +  });
 +
 +  it('should be true', () => {
 +    expect(true).toBe(true);
 +  });
 +});
 +</code>
 +
 +On inclus ''HeroesComponent'' et ''HeroComponent''.
 +
 +
 +===== Finding Elements by Directive =====
 +
 +Le component ''HeroComponent'' doit se répéter pour chaque héro trouvé.
 +
 +
 +Remarquez qu'on utilise ''By.directive()''.
 +
 +<code javascript>
 +it('should render each hero as a HeroComponent', () => {
 +  mockHeroService.getHeroes.and.returnValue(of(HEROES));
 +
 +  // run ngOnInit
 +  fixture.detectChanges();
 +
 +  const heroComponentDEs = fixture.debugElement.queryAll(
 +    By.directive(HeroComponent)
 +  );
 +  expect(heroComponentDEs.length).toEqual(3);
 +  for (let i = 0; i < heroComponentDEs.length; i++) {
 +    expect(heroComponentDEs[i].componentInstance.hero).toEqual(HEROES[i]);
 +  }
 +});
 +</code>
 +
 +
 +===== Integration Testing of Services =====
 +
 +On veut tester l'intégration du service ''HeroService'' avec le ''HttpClient''.
 +
 +<code javascript>
 +import { TestBed } from "@angular/core/testing";
 +import { HeroService } from "./hero.service";
 +import { MessageService } from "./message.service";
 +import { HttpClientTestingModule, HttpTestingController } from "@angular/common/http/testing";
 +
 +describe('HeroService', () => {
 +  let mockMessageService;
 +  let httpTestingController: HttpTestingController;
 +  let service: HeroService;
 +
 +  beforeEach(() => {
 +    mockMessageService = jasmine.createSpyObj(['add']);
 +
 +    TestBed.configureTestingModule({
 +      imports: [ HttpClientTestingModule ],
 +      providers: [
 +        HeroService,
 +        {provide: MessageService, useValue: mockMessageService}
 +      ]
 +    });
 +
 +    httpTestingController = TestBed.get(HttpTestingController);
 +    service = TestBed.get(HeroService);
 +  });
 +});
 +
 +</code>
 +
 +
 +===== Implementing a Test with Mocked HTTP =====
 +
 +
 +Ce qu'on veut tester, c'est la méthode suivante dans le service:
 +
 +
 +<code javascript>
 +getHero(id: number): Observable<Hero> {
 +  const url = `${this.heroesUrl}/${id}`;
 +  
 +  return this.http.get<Hero>(url).pipe(
 +    tap(_ => this.log(`fetched hero id=${id}`)),
 +    catchError(this.handleError<Hero>(`getHero id=${id}`))
 +  );
 +}
 +</code>
 +
 +
 +Alors, un exemple de test serait :
 +
 +<code javascript>
 +it('should call get with the correct URL', () => { 
 +  service.getHero(4).subscribe();
 +
 +  const req = httpTestingController.expectOne('api/heroes/4');
 +  req.flush({id: 4, name: 'SuperDude', strength: 100});
 +  httpTestingController.verify();
 +});
 +</code>
 +
 +==== Obtenir l'instance de service ====
 +
 +
 +Pour obtenir une instance de ''service'', on peut faire:
 +
 +<code javascript>
 +import { TestBed, inject } from '@angular/core/testing';
 +
 +// ...
 +
 +it('should call get with the correct URL', inject([HeroService], (service: HeroService) => {
 +  // ...
 +}));
 +</code>
 +
 +
 +----
 +
 +
 +====== Testing DOM Interaction and Routing Components ======
 +
 +
 +
 +
 +
 +====== Sources ======
 +
 +  * [[https://medium.com/ngconf/mockstore-in-ngrx-v7-0-f7803708de4e|MockStore in NgRx v7.0]]
  
  
-La mention '''' 
  
web/javascript/angular/unittests.1560204069.txt.gz · Dernière modification : 2022/02/02 00:43 (modification externe)