Как протестировать метод toHaveBeenCalled при модульном тестировании перехватчика ошибок

#angular #karma-jasmine

#angular #karma-jasmine

Вопрос:

Я пытаюсь сказать, что я хочу посмотреть, был ли вызван конкретный метод или нет. У меня есть перехватчик ошибок. Существует 3 метода (1 общедоступный и 2 частных метода). Вот код:

перехватчик

 import { ... } from '...';
...

@Injectable({ providedIn: 'root' })
export class ErrorInterceptor implements HttpInterceptor {
    constructor(private authService: AuthService) {}

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return next.handle(request).pipe(
            catchError(err => {
                if (err instanceof HttpErrorResponse) {
                    switch (err.status) {
                        case 400:
                        case 403:
                            // some logic
                            break;
                        case 401:
                            return this.handle401Error(request, next); // This I've to check
                        default:
                            // some logic
                    }
                }
                const error = err.error.message || err.statusText;
                return throwError(error);
            })
        );
    }

    private handle401Error(request: HttpRequest<any>, next: HttpHandler) { // will be called in case: 401
        // some logic
    }

    private addToken(request: HttpRequest<any>, token: string) { // ignore this method
      // some logic
    }
}
  

Вот мой файл спецификации:

 import { throwError, defer } from "rxjs";
import { ErrorInterceptor } from './error.interceptor';

describe('ErrorInterceptor', () => {
    let errorInterceptor;
    let authServiceSpy;

    beforeEach(() => {
        authServiceSpy = jasmine.createSpyObj('AuthService', ['logout']);
        errorInterceptor = new ErrorInterceptor(authServiceSpy);
    })

    describe('intercept', () => {
        let httpRequestSpy;
        let httpHandlerSpy;
        const error = {status: 401, statusText: 'error'};

        it('should auto logout if 401 response returned from api', () => {
            //arrange
            httpRequestSpy = jasmine.createSpyObj('HttpRequest', ['doesNotMatter']);
            httpHandlerSpy = jasmine.createSpyObj('HttpHandler', ['handle']);
            httpHandlerSpy.handle.and.returnValue(throwError(
                {error: 
                    {message: 'test-error'}
                }
            ));
            //act
            errorInterceptor.intercept(httpRequestSpy, httpHandlerSpy)
                .subscribe(
                    result => console.log('good', result), 
                    err => { 
                        console.log('error', err);
                        expect(err).toEqual('test-error');
                        expect(errorInterceptor.handle401Error).toHaveBeenCalled();  //Error: <toHaveBeenCalled> : Expected a spy, but got undefined.
                    }
                );
        })
    })
})
  

Когда я проверяю:

expect(errorInterceptor.handle401Error).toHaveBeenCalled();

Я получаю эту ошибку:

Error: <toHaveBeenCalled> : Expected a spy, but got undefined.

Пожалуйста, исправьте мою ошибку. Вот stackblitz.

Ответ №1:

Это ошибка спецификатора доступа, поскольку handle401Error это частный метод, вы не можете получить доступ напрямую по ссылке, как errorInterceptor.handle401Error с других страниц. Проверьте приведенные ниже способы;

Первый способ: поэтому я не предпочитаю утверждать, expect(errorInterceptor.handle401Error).toHaveBeenCalled(); вместо этого я включу логические тестовые примеры частного метода в родительский метод, где он был вызван.

Второй способ: вы можете получить ссылку на psudo, инициализировав или подсмотрев errorInterceptor["handle401Error"]

не уверен в синтаксисе в Jasmine, но, пожалуйста, обратитесь к приведенному ниже коду, который я использую в шутку

 // arrange
errorInterceptor["handle401Error"] = jest.fn();

// assert
expect(errorInterceptor["handle401Error"]).toHaveBeenCalled();
  

Комментарии:

1. Да, вы правы. Извините, я не понял, что вызываю частный метод. Сейчас я пробую ваш метод.