Unit test of method retrying HTTP requests

时间:2019-05-31 11:53:57

标签: angular unit-testing jasmine

I have method like this in my application:

public async onImport(importedCalculations: ImportCalculation, btn: HTMLButtonElement): Promise<void> {
        try {
            this.renderer.addClass(btn, 'loading');
            const response: any = await this.ics.import(importedCalculations.id);

            of(true).pipe(
                mergeMap(() => Observable.from(this.ics.getProcessQueue(response.id))),
                map((response: any) => {
                    if (response.state !== QueueState.READY) {
                        throw new Error('File is not ready');
                    }
                    return { ...response }
                }),
                retryWhen(genericRetryStrategy()),
                catchError(error => of(error))
            ).subscribe((response: ProcessQueue) => {
                this.refreshCollection({
                    ...importedCalculations,
                    imported: true
                });

                if (response.message) {
                    this.modalService.open(new LogsModal(response.message.split('<br>')))
                }

                this.renderer.removeClass(btn, 'loading');
            });

        } catch (e) {
            console.log(e);
            this.renderer.removeClass(btn, 'loading');

            if (e instanceof HttpErrorResponse) {
                if (e.status == 403) {
                    this.mgs.set403();
                }
                else {
                    this.mgs.set(`Wystąpił problem podczas przygotowywania pliku.`);
                }
            }

        }
    }

I want to unit test this using jasmine, such that the http request first returns an error but on a subsequent try, returns the expected data.

I try do this in this way:

 it('shoud...', async(() => {
        const spy = spyOn(ics, 'import').and.returnValue(Promise.resolve({ id: 1 }))
        spyOn(component, 'onImport').and.callThrough();
        spyOn(ics, 'getProcessQueue');
        component.importedCalculations = { items: mockCalculationImportData, total: 1 } as ApiResponse<ImportCalculation>;
        fixture.detectChanges();
        const button = debugElement.query(By.css('.reset')).nativeElement

        component.onImport(mockCalculationImportData[0], button);

        expect(button.classList).toContain('loading')

        spy.calls.mostRecent().returnValue.then(() => {
            expect(ics.reset).toHaveBeenCalledWith(mockCalculationImportData[0].id);

        })
    }))

and it works... but I want to test rest of code, and when i add

expect(ics.getProcessQueue).toHaveBeenCalledTimes(4)

in promise resolver test failed with error:

Expected spy getProcessQueue to have been called 4 times. It was called 1 times.

This is my mockup service:

const importCalculationsServiceStub = {
    state: 0,

    post() {
        return fakeAsyncResponse([{ id: 1 }]);
    },

    cget() {
        return fakeAsyncResponse({ items: mockCalculationImportData, total: 1 })
    },

    reset() {
        return fakeAsyncResponse([{ id: 1 }]);
    },

    get() {
        return fakeAsyncResponse({ url: 'test' })
    },

    open() {
        return fakeAsyncResponse({ url: 'test' })
    },

    getProcessQueue(id) {
        this.state++;
        if (this.state > 3) {
            return fakeAsyncResponse({ state: QueueState.READY })
        }
        return fakeAsyncResponse({ state: QueueState.PICKED_UP })
    }
};

Is there any possibility of achieving this and do this in the right way?

0 个答案:

没有答案