angularkarma-jasmine

Angular 18 httpClient testing expects


I just migrated my app angular version from angular 15 to angular 18. The app is running ok but my tests starts to fail when i switch the deprecated versions of httpClientModule to provideHttpClient(withInterceptorsFromDi()), provideHttpClientTesting()

so every expects that i use something like expect(httpClientSpy.get).toHaveBeenCalled(); is failling now.

Example:

describe('FinishedService', () => {
  let service: FinishedService;
  let httpTestingController: HttpTestingController;
  let httpClientSpy = jasmine.createSpyObj('HttpClient', [
    'get',
    'post',
    'put',
  ]);

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [BrowserAnimationsModule],
      providers: [
        { provide: HttpClient, useValue: httpClientSpy },
        provideHttpClient(),
        provideHttpClientTesting(),
      ],
    });
    service = TestBed.inject(FinishedService);
    httpTestingController = TestBed.inject(HttpTestingController);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  it('should update to finished step', () => {
    httpClientSpy.put.and.returnValue(of(void 0));
    const dummyShipmentData = {
      shipmentId: 1,
    };

    service.update(dummyShipmentData).subscribe();

    expect(httpClientSpy.put).toHaveBeenCalled();
  });

this test is failling but if i put the deprecated imports HttpClientModule, HttpClientTestingModule, it works.

Is there some new way to expect these htppRequests?

could it be some miss configuration in the .ts itself?

my service.ts constructor:

@Injectable({
  providedIn: 'root',
})
export class FinishedService extends BaseService {
  constructor(http: HttpClient) {
    super(http);
  }

main.ts:

bootstrapApplication(AppComponent, {
  providers: [
    importProvidersFrom(
      ...
    ),
    ...
    provideHttpClient(withInterceptorsFromDi()),
  ],
}).catch((err) => console.error(err));

Solution

  • You should probably change the tests to instead of using a Jasmine spy, they use the vanilla Http Test client angular provides.

    You will also need the HttpTestingController to build the expectations or to stub API calls. This service provides a comprehensive set of tests and validations (as per above link)

    Something like should help you getting started:

    TestBed.configureTestingModule({
      ...
      providers: [
        // ...
        provideHttpClient(),
        provideHttpClientTesting(),
      ],
    });
    const httpTesting = TestBed.inject(HttpTestingController);
      
    

    The problem with the Jasmine Spy usage is that it does not confirm with Angular's life-cycle hooks by itself. You could always make it comply and your tests might start working, but that would be a work around... I believe the proper solution would be to move the tests to be using HttpTestingController.