How to test an Angular service with inner subscriptions?

Discussão em 'Angular' iniciado por Chris Barr, Outubro 30, 2024.

  1. Chris Barr

    Chris Barr Guest

    I have an angular 18 service which I am trying to unit test. I have a setSelected method that a consumer simply calls, and it will update the subject when it's ready

    @Injectable({ providedIn: 'root' })
    export class TimesheetService {
    private readonly apiService = inject(ApiService);

    private readonly selectedTimesheetSubject$ = new BehaviorSubject<ITimesheet| undefined>(undefined);
    private readonly isLoadingSubject$ = new BehaviorSubject(false);

    public readonly selectedTimesheet$ = this.selectedTimesheetSubject$.asObservable();
    public readonly isLoading$ = this.isLoadingSubject$.asObservable();

    public setSelected(weekEndingDate: string): void {
    this.isLoadingSubject$.next(true);
    this.error = undefined;

    this.apiService.getTimesheet$(weekEndingDate).subscribe({
    next: (res) => {
    this.isLoadingSubject$.next(false);
    this.selectedTimesheetSubject$.next(res);
    },
    error: (err) => {
    this.isLoadingSubject$.next(false);
    console.error('error!', err);
    },
    });
    }

    public clearSelected(): void {
    this.selectedTimesheetSubject$.next(undefined);
    }
    }


    How do I test this? I need to test that when the method is called it updates all the subjects as I expect them to, but I don't know how to either hook into or wait on that subscription inside

    it('should set the selected timesheet based on a passed in date', async () => {
    const weekEnding = DateTime.fromISO('2024-11-02');
    const expectedInterval = Interval.fromDateTimes(weekEnding, weekEnding);
    injectedApiService.getTimesheet$.and.nextOneTimeWith([mockSelfTimesheet]);

    service.setSelected('2024-11-02');

    //Check that the initial values are correct BEFORE the subscription completes
    expect(await lastValueFrom(service.isLoading$)).toBeTrue();
    expect(await lastValueFrom(service.selectedTimesheet$)).toBeUndefined();
    expect(injectedApiService.getTimesheet$).toHaveBeenCalledOnceWith(expectedInterval, false);

    //How do I check these values AFTER the subscription completes?
    // expect(await lastValueFrom(service.isLoading$)).toBeFalse();
    // expect(await lastValueFrom(service.selectedTimesheet$)).toEqual(mockSelfTimesheet);
    });


    Right now with the above test I just get this error

    Error: Timeout - Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)


    and I'm not sure what I'm doing wrong. How can I call the service method and test the values of my externally-facing Observables before and after the subscription completes?

    Continue reading...

Compartilhe esta Página