web-dev-qa-db-fra.com

Test unitaire Angular 2

J'essaie d'écrire un test pour un service angular qui a une propriété Subject et une méthode pour appeler .next() sur ce sujet.

Le service est le suivant:

@Injectable()
export class SubjectService {
  serviceSubjectProperty$: Subject<any> = new Subject();

  callNextOnSubject(data: any) {
    this.serviceSubjectProperty$.next(data);
  }
}

Et le fichier de test pour ce service:

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

import { SubjectService } from './subject.service';

describe('SubjectService', () => {

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        SubjectService
      ]
    });
  });

  it('callNextOnSubject() should emit data to serviceSubjectProperty$ Subject',
    inject([SubjectService], (subjectService) => {
      subjectService.callNextOnSubject('test');

      subjectServiceProperty$.subscribe((message) => {
        expect(message).toBe('test');
      })
  }));
});

Le test passe toujours l'événement si je change l'argument de subjectService.callNextOnSubject de 'test' à autre chose.

J'ai également essayé de tout emballer avec async et fakeAsync, mais le résultat est le même.

Quelle serait la bonne façon de tester si callNextOnSubject émet des données vers le serviceSubjectProperty$ Matière?

7
crdevdeu

J'ai trouvé cet article en recherchant la solution:

http://www.syntaxsuccess.com/viewarticle/unit-testing-eventemitter-in-angular-2.

et ça a bien marché pour moi (c'est très court, n'ayez pas peur de l'ouvrir).

Je le colle ici, alors peut-être que cela aidera ceux qui sont venus sur ce site à la recherche d'une réponse.


Concernant la question posée - je pense que vous devez changer:

  subjectService.callNextOnSubject('test');

  subjectServiceProperty$.subscribe((message) => {
    expect(message).toBe('test');
  })

à

  subjectServiceProperty$.subscribe((message) => {
    expect(message).toBe('test');
  })

  subjectService.callNextOnSubject('test');

, alors abonnez-vous d'abord, puis émettez un événement.

Si vous émettez 'test' avant l'abonnement, rien ne "rattrapera" cet événement.

9
pbialy

L'utilisation du rappel jasmine 'done' fera l'affaire jusqu'à présent, consultez la documentation ci-dessous: https://jasmine.github.io/api/Edge/global (voir implementationCallback (doneopt))

Ci-dessous un exemple utilisant votre cas de test:

it('callNextOnSubject() should emit data to serviceSubjectProperty$ Subject', (done) => {
    inject([SubjectService], (subjectService) => {
      subjectService.callNextOnSubject('test');

      subjectServiceProperty$.subscribe((message) => {
        expect(message).toBe('test');
        done();
      })
  }) // function returned by 'inject' has to be invoked
});
1
mth khaled

Vous devez tester les données dont le composant a changé après l'appel de votre sujet. Devrait tester uniquement des variables publiques, non privées ou protégées; Par exemple:

un service:

@Injectable()
export class SomeService {
    onSomeSubject: Subject<any> = new Subject();

    someSubject(string: string) {
        this.onSomeSubject.next(string);
    }
}

composant:

export class SomeComponent {
    @Input() string: string;

    constructor(private service: SomeService) {
        service.onSomeSubject.subscribe((string: string) => {
            this.string = string;
        }); //don't forget to add unsubscribe.
    }
}

tester:

...
describe('SomeService', () => {
    let someService: SomeService; // import SomeService on top
    let someComponent: SomeComponent; // import SomeService on top

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [SomeService, SomeComponent]
        });
        injector = getTestBed();
        someService = injector.get(SomeService);
        someComponent = injector.get(SomeComponent);
    });

    describe('someSubject', () => {
        const string = 'someString';

        it('should change string in component', () => {
            someService.someSubject(string);
            expect(someComponent.string).tobe(string);
        });
    });
});
1
Pasha Sybiriak