angular - Enhetstest: Mocking-tjänst som returnerar observables för att returnera subjects för att testa förändring av värden över tid orsakar att TS kastar TS2339


Jag har en tjänst som returnerar värdena som exponeras av ngrx-selektorer, och en komponent som definierar denna tjänst, injicerar den och sätter egenskaper baserat på de värden som returneras av tjänsten.

Jag skriver enhetstester för komponenten med en mock av tjänsten, och jag behöver att mock-tjänsten returnerar olika värden för varje enhetstest. För att göra detta har jag definierat mock-tjänstklassen så att den returnerar subjects istället för observables. Tester körs, men TS kastar ett fel som säger att gränssnittet för mock-tjänsten inte matchar gränssnittet för den riktiga tjänsten, eftersom den riktiga tjänsten returnerar observables.

Stackblitz

Stackblitz fungerar och testerna körs korrekt, men som du kan se ger TS felet TS2339: Egenskapen 'next' finns inte på typen 'Observable'

Jag har upptäckt att jag kan lägga till/@ts-ignore ovanför varje anrop till .next() för att få TypeScript-kompilatorn att ignorera felet, men det verkar inte vara den bästa lösningen.

Kanske finns det ett bättre sätt att göra narr av tjänsten helt och hållet så att den fortfarande returnerar observables, men jag kan returnera ett annat värde för varje enhetstest?

Svar #1

Du kan ha den verkliga tjänsten OCH mocken att returnera samma sak, genom att använda .asObservable()-metoden på BehaviorSubject. Du kan också använda do()-metoden du har för att sätta ett nytt värde i BehaviorSubject.

För att demonstrera satte jag ihop detta StackBlitz. Här är MockTestService från det StackBlitz:

MockTestService {
    private _test$ = new BehaviorSubject(10);
    public test$ = this._test$.asObservable();
    do(param: number): void { this._test$.next(param); }
}  

Jag hoppas att detta hjälper.

Relaterade artiklar