Имам ъглово приложение, за което се опитвам да създам единичен тест. Има конкретен метод, който създава наблюдаема чрез сложна верига от наблюдаеми канали и обещания и след това впоследствие се абонира за тази създадена наблюдаема. Трябва да проверя, че извикването на метод е направено вътре в абонамента.
Структурата е нещо като това:
private obs$: Observable<T>;
private subscription: Subscription;
methodToTest(): void {
this.obs$ = from( ... ).then( /* chain of piped observables */ );
this.subscription = this.obs$
.subscribe(
(value: T) => {
// bunch of logic
methodToBeVerifiedWasCalled();
},
(error) => { /* error handling */ }
);
}
Моят тест досега изглежда така:
it('the method to be verified is successfully called', () => {
// various mocking set up
this.mockApi.methodThatReturnsAPromise.and.returnvalue(Promise.resolve());
// etc.
this.classUnderTest.methodToTest();
// assertions for the various mocks...
expect(this.mockApi.methodThatReturnsAPromise).toHaveBeenCalled();
// etc.
// assert that the target method was called:
expect(this.classUnderTest.methodToBeVerifiedWasCalled).toHaveBeenCalled();
expect(this.classUnderTest.subscription).toBeDefined();
});
Разбира се, този тест се проваля при последните твърдения, защото methodToBeVerifiedWasCalled
всъщност се извиква вътре в блока за абониране и тестът просто преминава през него синхронно. (Тук classUnderTest
е шпионски обект с methodToBeVerifiedWasCalled
, който е шпиониран.)
Тъй като методът присвоява стойност на наблюдаемото, не мога просто да се абонирам за classUndertest.obs$
в асинхронен тест и да проверя върнатата стойност (което така или иначе всъщност не помага за решаването на проблема.) Как мога да проверя, че методът вътре в блока за абониране се нарича?
Не мога да променя изходния код, само тестовете.