Testing the subscribe function in Angular within a returned Promise: A guide

I am facing an issue with a service that returns a Promise. It retrieves data from a JSON file using a subscribe method before resolving the Promise.

I am trying to test the result of this Promise based on the parameters I provide, but I am encountering two problems. Either the test times out with an error message saying "Exceeded timeout of 5000 ms for a test," or the test passes incorrectly because the subscribe part is not being executed.

service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';


export interface IAppConfig {
  env: {
    name: string;
  };
  features: {
    [key: string]: boolean;
  };
}

@Injectable({
  providedIn: 'root',
})
export class ConfigService {


  static appSettings: IAppConfig;

  constructor(private http: HttpClient) {}

load() {
    const jsonFile = displayJsonFile
      ? `../../../../assets/.json1`
      : `../../../../assets/.json2`;

    return new Promise<any>((resolve) =>
      this.http.get(jsonFile).subscribe((res) => {
    appSettings = res
    resolve(res);
    })
    );
  }
}

  import { TestBed, tick } from '@angular/core/testing';

import { ConfigService } from './config-service.service';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpClient } from '@angular/common/http';

describe('ConfigService', () => {
  let service: AppConfigService;
  let httpMock: HttpTestingController;

  const mockConfig = {
    env: {
      name: 'json1',
    },
    features: {
      feature1: true,
      feature2: true,
    },
  };

  
  beforeEach(() => {
    TestBed.configureTestingModule({ imports: [HttpClientTestingModule] });
    service = TestBed.inject(AppConfigService);
    httpMock = TestBed.inject(HttpTestingController);
  });

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

  
  it('should load config file when environment is prod', () => {
    service.load().then(res => expect(res).toBe(mockConfig)
    
  });

});

Answer №1

The examination required incorporating a portion of the response mentioned by @Chintan Dhokai and making an adjustment to accommodate the observable element:

import { TestBed, tick } from '@angular/core/testing';
import { AppConfigService } from './app-config.service';
import {
  HttpClientTestingModule,
  HttpTestingController,
} from '@angular/common/http/testing';
import { HttpClient } from '@angular/common/http';
import { of } from 'rxjs';

describe('AppConfigService', () => {
  let service: AppConfigService;
  let httpMock: HttpClient;
  const mockConfig = {
    env: {
      name: 'json1',
    },
    features: {
      feature1: true,
      feature2: true,
    },
  };

  beforeEach(() => {
    TestBed.configureTestingModule({ imports: [HttpClientTestingModule] });
    service = TestBed.inject(AppConfigService);
    httpMock = TestBed.inject(HttpClient);
  });

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


  it('should retrieve configuration file', async () => {
    const spyHttp = jest.spyOn(httpMock, 'get');
    spyHttp.mockReturnValue(of(Promise.resolve(mockConfig)));
    const result = await service.load();
    expect(result).toEqual(mockProdConfig);
  });
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Obtain the string value for the template variable

Trying to display a string literal if element.elementId is null or undefined. <div>{{String(element.elementId)}}</div> Encountering an error: TableBasicExample.html:6 ERROR TypeError: _co.String is not a function at Object.eval [as updat ...

When using Angular 10 or later, the mouseclick event will consistently trigger Angular's change detection mechanism

When I bind an event to elements on a component's HTML page, the component continues to detect changes even when the element event is fired. Despite setting the change detection mode of the component to OnPush, this behavior persists. To test this, I ...

Data from graphql is not being received in Next.js

I decided to replicate reddit using Next.js and incorporating stepzen for graphql integration. I have successfully directed it to a specific page based on the slug, but unfortunately, I am facing an issue with retrieving the post information. import { use ...

Error: The value of this.root_ is currently null

Attempting to utilize the material from https://github.com/material-components/material-components-web/tree/master/packages/mdc-drawer to make it work and facing challenges The code I am using: <aside class="mdc-drawer mdc-drawer--dismissible"> ...

Encountering "environment.prod.ts path does not exist in file replacements" error while Dockerizing Angular build

I am encountering an issue with a Dockerfile that throws an error during the build process. I attempted to install the angular/cli globally and run ng build --prod using a separate RUN command, but the same error persists. Dockerfile FROM node:12.17.0-al ...

What could cause a member variable to be uninitialized in the ngInit method in Ionic/Angular, even though it was initially set in the constructor

Despite setting the modal form to be bound to an instance of "Foo" during its construction, I encountered a strange issue where, post-constructor, this.foo became undefined. Even after verifying this through breakpoints and console.log, the problem persist ...

Unable to associate with 'ngIf' as it is not recognized as a valid attribute for 'table'

I've attempted multiple solutions suggested here but none seem to be working. Can someone please assist me? My component.ts is functioning correctly and fetching values without any errors in the console, however, nothing is appearing on the HTML page ...

JSX tags without any inner content should be self-closed

After successfully running this code, I encountered an issue when committing it to git. The error message 'ERROR: src/layouts/index.tsx:25:9 - JSX elements with no children must be self-closing' appeared. I attempted to resolve the error by addi ...

Is TypeScript necessary, or can I simply stick with ES6?

As a client developer using AngularJS in my daily job, we are considering transitioning to TypeScript. After researching TypeScript, I discovered that most JavaScript packages I require need definition type files. This can be inconvenient, especially whe ...

Is it impossible to use type as a generic in TypeScript?

Struggling with TypeScript in React and encountered an issue. I decided to use a generic to build an abstracted class related to Axios. However, I ran into an ESLint error when using any as the type parameter for my generic. ESLint: Unexpected any. Specif ...

Encountering ng build --prod errors following Angular2 to Angular4 upgrade

Upon completing the upgrade of my Angular2 project to Angular4 by executing the following command: npm install @angular/common@latest @angular/compiler@latest @angular/compiler-cli@latest @angular/core@latest @angular/forms@latest @angular/http@latest @an ...

Tips for displaying an array and iterating through its children in Angular 7

I am currently working on extracting the parent and its children to an array in order to display them using ngFor. However, I am encountering an issue where the children are not being displayed during the ngFor. I have a service that retrieves data from a ...

How to make sure a bootstrap row fills the rest of the page without exceeding the height of the screen

In my Angular application, I am using bootstrap to create the following structure (simplified version). <div class="container"> <div class="header> <div class="mat-card> <!-- Header content --> < ...

The function mockResolvedValueOnce now returns a promise instead of the specified value

import products from "services/products"; jest.mock("services/products", () => { return { getProducts: jest .fn() .mockImplementation(() => Promise.resolve([product, product])), }; }); ( ...

What is the best way to trigger a Redux Toolkit action within a React Router DOM action?

My router setup looks like this: const router = createBrowserRouter([ { path: "/", element: <MainLayout />, errorElement: <Error />, children: [ { path: "/inventory", element: <Inve ...

Issue with bidirectional binding on angular material slide toggle not functioning as anticipated (Angular 4)

My angular material slide-toggle implementation seems to be working, but I'm facing an issue where it doesn't bind the value to the relevant variable as expected. // other irrelevant imports above.. import {MatDialog, MatDialogRef, MAT_DIALOG_DA ...

What is the best way to save a Map for future use in different components?

Let's say I define an enum like this: export enum SomeEnum { SomeLongName = 1, AnotherName = 2 } Within my display components, I'm utilizing an enum map to translate the enum values into strings for presentation on the web app: enumMap = new Map ...

Receiving an error while trying to install packages from the NPM registry due to non

I am facing some challenges while attempting to install my Ionic App through the registry along with its dependencies. I have been using npm i --loglevel verbose command, and my ~/.npmrc file is configured as follows: //nexus.OMMITED.com/repository/:_auth ...

Discover the combined type of values from a const enum in Typescript

Within my project, some forms are specified by the backend as a JSON object and then processed in a module of the application. The field type is determined by a specific attribute (fieldType) included for each field; all other options vary based on this ty ...

How can you determine the number of times a particular digit appears around a specific position in a TypeScript array

(Utilizing Typescript for assistance) I am looking to determine the number of occurrences of the digit 2 surrounding a specific position within an array. The function takes in the position coordinates as parameters - param 1 for row and param 2 for column. ...