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
thehttp.get(...)
function in my test which caused the above error to be eliminated but it didn't call myintercept
function when I did that.
Any help is much appreciated - thank you!