angular - Angular2 - Testa en funktion som anropar en http-tjänst inuti


Jag försöker för närvarande att testa en funktion som anropar en HTTP-förfrågningsservice och sedan gör något i subscribe-delen (anropar en funktion och sätter en variabel). Mitt tillvägagångssätt hittills har varit att bara anropa funktionen och jag trodde att request-servicen skulle anropas automatiskt och att subscribe-delen därför skulle köras. Men jag känner att detta inte är rätt sätt att göra det på eftersom det inte fungerar.

Funktionen jag vill testa:

  public trainBot() {
    this.isTraining = true;
    this.requestsService.trainModel(this.botId, false)
      .subscribe(response => {
        this.trainingStatus = this.trainingStatusMapping[response['status']];
        this.pollTrainingStatus();
      });
  }

Mitt test hittills (som inte fungerar).

it('should poll the training status', () => {
    spyOn(component, 'pollTrainingStatus').and.callThrough();
    component.trainBot();
    fixture.detectChanges();
    expect(component.pollTrainingStatus).toHaveBeenCalled();
  });

Så, kan någon säga till mig hur man testar den delen inuti .subscribe(... delen?

Uppdatering:

Som någon föreslog lade jag till returnValue och async till mitt test. De fungerar fortfarande inte, men ser ut så här nu:

it('should poll the training status', fakeAsync(() => {
    component.trainBot();
    spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
    spyOn(component, 'pollTrainingStatus').and.callThrough();
    fixture.detectChanges();
    tick(1);
    expect(service.trainModel).toHaveBeenCalled();
    expect(component.pollTrainingStatus).toHaveBeenCalled();
  }));

Felet är detsamma

Svar #1

För det första behöver du skapa dina spioner INNAN du kör metoden trainBot(). Det borde fixa dina tester.

it('should poll the training status', () => {
  spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));
  spyOn(component, 'pollTrainingStatus');

  component.trainBot();

  expect(service.trainModel).toHaveBeenCalled();
  expect(component.pollTrainingStatus).toHaveBeenCalled();
}));

Men låt oss prata om dina teststrategier.

Ärligt talat testar du en komponent, inte tjänsten, så du borde inte låta tjänstmetoden anropas.

spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));

Dessutom bör ett enhetstest testa det minsta möjliga. Du testar faktiskt callbacken här, och callbacken borde förmodligen vara en namngiven metod istället för en anonym pilfunktion. Då kan du testa och verifiera callbackens funktionalitet i andra tester.

public trainBot() {
  this.isTraining = true;
  this.requestsService.trainModel(this.botId, false)
      .subscribe(response => this.onTrainbotSuccess(response));
}

public onTrainbotSuccess(response) {
  this.trainingStatus = this.trainingStatusMapping[response['status']];
  this.pollTrainingStatus();
}

I detta test kan du testa att svarmetoden kallas

it('should call service.trainModel', () => {
  spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));

  component.trainBot();

  expect(service.trainModel).toHaveBeenCalled();
});

it('should send success responses to onTrainbotSuccess()', () => {
  spyOn(component, 'onTrainbotSuccess');
  spyOn(service, 'trainModel').and.returnValue(Observable.of({'status': 'training'}));

  component.trainBot();

  expect(component.onTrainbotSuccess).toHaveBeenCalled();
});

Nu kan vi skriva tester för exakt vad framgångsåteranropet gör.

it('should poll the training status', () => {
  spyOn(component, 'pollTrainingStatus');

  component.onTrainbotSuccess({'status': 'training'});

  expect(component.pollTrainingStatus).toHaveBeenCalled();
});

Svar #2

Funktionen som skickas till subscribe() anropas asynkront. Detta betyder att din assertion körs innan this.pollTrainingStatus() anropas. Du behöver använda async() eller fakeAsync() hjälpfunktion.

I koden kan det se ut så här (om man använder fakeAsync()):

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

it('should poll the training status', fakeAsync(() => {
  ...
  expect(component.pollTrainingStatus).toHaveBeenCalled();
}));

Relaterade artiklar