如何在单元测试错误拦截器中测试toHaveBeenCalled的方法

时间:2020-08-24 14:05:48

标签: 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 个答案:

答案 0 :(得分:1)

这是一个访问说明符错误,因为handle401Error是私有方法,因此无法像其他其他页面上的errorInterceptor.handle401Error这样的引用直接访问。检查以下方式;

第一步:因此,我不希望声明expect(errorInterceptor.handle401Error).toHaveBeenCalled();,而是将私有方法的逻辑测试用例包含在调用它的父方法中。

次要:您可以通过初始化或监视errorInterceptor["handle401Error"]

来获得伪参考。

不确定Jasmine中的语法,但是请参考下面我在玩笑中使用的代码

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

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