5

I'm working on an Angular 10 application that uses an HttpInterceptor for adding a specific header to all responses. Unfortunately, when trying to test this interceptor, I keep getting the following error:

Error: Expected one matching request for criteria "Match by function: ", found none.

Or a similar variant:

Error: Expected one matching request for criteria "Match URL: /endpoint", found none.

My expectation is that this test would pass but I'm, now, at a loss as to figuring out why it's not working.

Here is my interceptor:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    constructor(private kc: KeycloakService) { }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return Observable.fromPromise(this.kc.getToken()).mergeMap(auth => {
            if (auth) {
                req = req.clone({
                    setHeaders: {
                        Token: auth
                    }
                });
            }

            return next.handle(req);
        })
    }
}

Here is my test:

// imports removed for clarity

describe('Interceptor', () => {
    let http: HttpClient;
    let httpController: HttpTestingController;
    let mockKeycloakService: KeycloakService;
    let interceptor: AuthInterceptor;

    const TEST_TOKEN = 'test-token';

    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [HttpClientTestingModule],
            providers: [
                KeycloakService,
                {
                    provide: HTTP_INTERCEPTORS,
                    useClass: AuthInterceptor,
                    multi: true
                }
            ],
        });

        http = TestBed.inject(HttpClient);
        httpController = TestBed.inject(HttpTestingController);
        mockKeycloakService = TestBed.inject(KeycloakService);

        spyOn(mockKeycloakService, 'getToken').and.returnValue(new Promise<string>(() => TEST_TOKEN));

        interceptor = new AuthInterceptor(mockService);
    });

    // removed for clarity

    it('adds token to all responses', done => {
        let endpoint = '/endpoint';
        http.get<HttpResponse<any>>(endpoint).subscribe(res => {
            expect(res).toBeTruthy();
            expect(res.headers).toBeTruthy();
            expect(res.headers.get('Token')).toBe(TEST_TOKEN);
        });
        let req = httpController.expectOne(endpoint);

        // The first error occurred when I tried this:
        // let req = httpController.expectOne(res => res.headers.has('Token') && res.headers.get('Token') === TEST_TOKEN);

        let body = { test: 'test-value' };
        console.log(`The URL is: ${req.request.url}`);
        expect(req.request.body).toEqual(body);

        req.flush(body);
        httpController.verify();
    });

    // removed for clarity
});

That said, it's probably worth pointing out that I've tried applying solutions from the following resources to no avail (most seem to be similar to what I already have anyways and many seem to be for older versions of Angular):

  • Unit testing HttpInterceptor from Angular 4: Here, I found a useful article that does almost exactly what I need but it doesn't actually work for my case (I'm getting the above errors). I say almost exactly because the Service I'm using to get the token doesn't actually use HttpClient from what I can tell.
  • This isn't exactly like my issue but it was similar enough to try it out. I tried using the workaround described by textbook but apparently that wasn't close enough to the issue I was having.
  • I also tried to spyOn the http.get(...) function in my test which caused the above error to be eliminated but it didn't call my intercept function when I did that.

Any help is much appreciated - thank you!

1
  • Instead of calling HttpClient directly inside the test method, have you ever tried to call a your service that makes use of HttpClient? Can you make your code available on stackblitz? Commented Jun 30, 2021 at 19:28

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.