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

Exclude the initial argument from functions listed within a JSON structure

Is there a way to create a generic type that reflects a JSON object structure, but excludes the first argument from functions while maintaining the types of other arguments? type InputType<T> = { increment: (state: T) => T, add: (state: T, cou ...

Exclude<Typography, 'color'> is not functioning correctly

Take a look at this sample code snippet: import { Typography, TypographyProps } from '@material-ui/core'; import { palette, PaletteProps } from '@material-ui/system'; import styled from '@emotion/styled'; type TextProps = Omi ...

What is the method for declaring personalized environment variables in Angular?

I am looking to utilize a different environment variable called test. The purpose behind this is to set up an http interceptor for my integration tests. This interceptor should specifically return a mocked response with predefined data and is intended for ...

Use a function on values that have corresponding keys in a separate array

I am working with a form.value object that looks like this: form.value = { "to_date": "2019-03-21T05:00:00.000Z", "from_date": "2019-03-13T05:00:00.000Z", "is_form": "" "errors":"" } Additionally, I have an array called filterArray: filterArray ...

Setting up a new folder in the internal storage within a React Native Expo environment

In my React Native Expo project, I am utilizing two functions to store data in a JSON file and then save the file to internal storage. However, the code currently asks for permission to store inside a chosen folder, but does not create the "ProjectName" fo ...

Error: Jest react testing encountered an issue when attempting to read the property 'type' from an undefined value

While conducting tests on my app components created with the material UI library using jest and enzyme, I encountered an error in one of my packages. Here is a screenshot of the error: Click here to view ...

Testing the addition of a dynamic class to an HTML button using Jasmine unit tests

I am brand new to Jasmine and currently in the process of grasping how to write Unit tests for my components in Angular 4. One issue I encountered is when I attempt to add a class to the button's classList within the ngOnInit() lifecycle hook of the C ...

Assign a true or false value to every attribute of an object

Imagine we have a scenario with an interface like this: interface User { Id: number; FirstName: string; Lastname: string; Age: number; Type: string; } and a specific method for copying properties based on a flag. ...

"Every time you run mat sort, it works flawlessly once before encountering an

I am having an issue with a dynamic mat table that includes sorting functionality. dataSource: MatTableDataSource<MemberList>; @Output() walkthroughData: EventEmitter<number> = new EventEmitter(); @ViewChild(MatSort, { static: true }) sort ...

Conceal the header on signup and login pages using Material UI

I am working on a project with three pages: SignUp, Login, and Lists, along with a header component. My goal is to hide the header on the SignUp and Login pages, and only show it on the List page. Any suggestions on how I can achieve this? Here is my cod ...

Customize the Default Functionality in Angular Material Expansion Panel Header

I'm currently attempting to customize the collapse and expand functionality of the Angular Material Expansion Panel. By default, when a user clicks anywhere in the Panel Header, the Expansion Panel will toggle between expanding and collapsing. My go ...

Can Observable subscriptions in Angular be tested?

I'm a newcomer to angular and I'm currently working on creating unit tests for the function below. HomeComponent.ts ngOnInit() { this.msalBroadcastService.inProgress$ .pipe( filter((status: InteractionStatus) => status === ...

Oops! An issue occurred: [RunScriptError]: Running "C:Windowssystem32cmd.exe /d /s /c electron-builder install-app-deps" resulted in an error with exit code 1

query: https://github.com/electron/electron/issues/29273 I am having trouble with the installation package as it keeps failing and showing errors. Any tips or suggestions would be highly appreciated. Thank you! ...

Encountering issues with Socket.io: consistently experiencing websocket connection failures along with persistent 404 errors on the

I am facing issues with setting up a websocket using socket.io. The server-side seems to be making a GET call successfully, but on the client-side, I am getting a 404 error: GET http://localhost:6543/socket.io/?uuid=258c4ab9-b263-47ca-ab64-83fe99ea03d4& ...

Error encountered with next-auth and the getServerSession function

Whenever I try to use the getServerSesssion function with all the necessary parameters, it results in a type error. In my code, I have the getServerAuthSession function defined as shown below: import { authOptions } from '@/pages/api/auth/[...nextauth ...

"Tips for removing all child elements from a parent element using Angular's Renderer2 in versions 5 and above

Manipulating the DOM programmatically is recommended using Angular's Renderer2. Within my directive, I extract some text from el.nativeElement.innerText, modify it, and aim to append it to my element: const text = renderer.createText(`${el.innerTex ...

Eliminate a specific choice from a drop-down menu in an Angular application

I am implementing a feature where clicking on a button adds more select drop downs. I want to ensure that the selected options in these new dropdowns do not duplicate any already chosen options. Below is the code snippet used for the select drop down: < ...

What could be causing TypeORM to create an additional column in the query

Why does this TypeORM query produce the following result? const result6 = await getConnection() .createQueryBuilder() .select('actor.name') .from(Actor,'actor') .innerJoin('actor.castings',&apos ...

How can the Calendar Ant Design showcase events that have fluctuating dates?

Seeking a solution to display events on an Ant Design Calendar using dateCellRender with dates stored in a variable object. Here's an example of the object: [ { "id": 1, "content": "Example", & ...

How to retrieve the value of an input field in Angular 2/Typescript without using ngModel

Currently, I'm utilizing Typescript in conjunction with Angular2, mirroring the structure of the Angular2 Tour of Heroes guide. There is a specific input field that I aim to associate a change event with, triggering custom logic whenever the value wi ...