Maria K.
Maria K.

Reputation: 229

HttpClient does not fire POST request in Jest test

I have a basic HttpInterceptor which appends content-type to my post requests:

import { Injectable } from '@angular/core';
import {
  HttpHandler,
  HttpInterceptor,
  HttpRequest,
} from '@angular/common/http';

@Injectable()
export class MyInterceptor implements HttpInterceptor {
  public intercept(
    request: HttpRequest<Record<string, unknown>>,
    next: HttpHandler,
  ) {
    console.log('REQUEST WAS INTERCEPTED');
    if (
      (request.method === 'POST' )
    ) {
      request = request.clone({
        setHeaders: {
          'Content-Type': 'application/json;charset=UTF-8',
        },
      });
    }

    return next.handle(request);
  }
}

Here is the test:

import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';

import { Data } from '@angular/router';
import { HttpClient, HTTP_INTERCEPTORS } from '@angular/common/http';
import { MyInterceptor } from './my-interceptor.service';

const testData: Data[] = [{ name: 'bob' }, { name: 'alice' }];

describe('PROVIDE_CONTENT_TYPE_HTTP_INTERCEPTOR', () => {
  let http: HttpClient;
  let httpTestingController: HttpTestingController;

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

    http = TestBed.inject(HttpClient);
    httpTestingController = TestBed.inject(HttpTestingController);
  });

  afterEach(() => {
    httpTestingController.verify();
  });

  it('handles POST requests', (done) => {
    http.post('/data', {}).subscribe((data: any) => {
      console.log('POST REQUEST HAS FIRED - NEVER HAPPENS');
      expect(data).toEqual(testData);
      done();
    });
    const request = httpTestingController.expectOne('/data');
    request.flush(testData);
  });

  it('ignores GET requests', (done) => {
    http.get('/data').subscribe((data: any) => {
      console.log('GET REQUEST HAS FIRED - SUCCESS');
      expect(data).toEqual(testData);
      done();
    });
    const request = httpTestingController.expectOne('/data');
    request.flush(testData);
  });
});

While GET request is fired, POST request never happens so that the first test fails with "Expected one matching request for criteria "Match URL: /data", found none.".

To me it does not look like some async issue - no request is logged from the intercepter itself.

Tested in Angular 12 and 13 (Node 14.17), without success. It used to work in Angular 11. I wonder if the implementation of HttpTestingModule changed? Why does GET request is sent while POST not?

I tried to use a wrapper service around HttpClient, it does not work neither.

Here is the minimal reproducible code on GitHub

Upvotes: 2

Views: 669

Answers (2)

Lars Gyrup Brink Nielsen
Lars Gyrup Brink Nielsen

Reputation: 4105

As a first step when troubleshooting strange situations like this, make sure the versions of the following dependencies are compatible:

  • jest
  • jest-preset-angular
  • ts-jest
  • ts-node
  • typescript
  • @angular/cli
  • @angular/core
  • The Angular builder used by your test target, for example @angular-devkit/build-angular for Karma + Angular CLI, @nrwl/jest:jest for Jest + Nx, or @angular-builders/jest for Jest + Angular CLI
  • Node.js

For Node.js, TypeScript, Angular CLI, and Angular Core compatibility refer to this compatibility matrix.

Then review your Jest configurations and presets.

Upvotes: 0

mbojko
mbojko

Reputation: 14699

setHeaders in clone() looks to have been deprecated in 14:

https://angular.io/api/common/http/HttpRequest

compare to:

https://v12.angular.io/api/common/http/HttpRequest

Upvotes: 1

Related Questions