Experimenting with a module reliant on two distinct services

I am facing an issue with a component that relies on a service to fetch data. The service also retrieves configurations from a static variable in the Configuration Service, but during Karma tests, the const variable is showing up as undefined.

Although I know I can create a mock service, I am unsure whether creating 2 services to test this component is the right approach. Additionally, if I do need to create mock services for other components that use the Configuration Service, it seems like a lot of extra work without a clear solution :( I have included both the ConfigurationService and the Service being used, in case that helps.

TypeError: Cannot read property 'apiUrl' of undefined

The apiUrl property is part of the conf static variable in the ConfigurationService.

ConfigService.ts

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

import * as YAML from 'js-yaml';
import {Config} from './models/Config';


@Injectable()
export class ConfigService {
  public static  conf: Config;

  constructor(private http: HttpClient) {}
   async load() {
       const res = await this.http.get<Config>('assets/config.yml', {responseType: 'text' as 'json'}).toPromise();
       ConfigService.conf = YAML.load(res).environment;
  }
}

InfoService.ts

export class InfoService {
  private InfoUrl = ConfigService.conf.apiUrl + '/info';

  constructor(private http: HttpClient) {}
  getInfo(){
    return http.get(InfoUrl);
  }
}

InfoComponent.ts

export class InfoComponent implements OnInit {
  private info;
  constructor(private infoService: InfoService) {}

  ngOnInit() {}

  loadInfo() {
    this.info = this.infoService.getInfo();
  }

InfoComponent.spec.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { InfoComponent } from './info.component';
import {HttpClientModule} from '@angular/common/http';
import {InfoService} from './info.service';
import {ConfigService} from '../shared/config.service';


describe('InfoComponent', () => {
  let component: InfoComponent;
  let fixture: ComponentFixture<InfoComponent>;

  beforeEach(async(() => {
     TestBed.configureTestingModule({
      imports: [HttpClientModule],
      declarations: [InfoComponent],
      providers: [
          ConfigService
          InfoService,
      ],
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(InfoComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

   it('should create', () => {
     expect(component).toBeTruthy();
   });
});

Answer №1

Essentially, your component requires the use of InfoService. The fundamental principle of Unit testing is to isolate the target code and test it independently. Therefore, in this scenario, there should not be a dependency created on ConfigService. It is advisable to have a separate Unit test specifically designated to assess the behavior of ConfigService.

class InfoServiceStub {
  getInfo(){
    return of({
        /// your mock data
     });
  }
}


describe('InfoComponent', () => {
  let component: InfoComponent;
  let fixture: ComponentFixture<InfoComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientModule],
      declarations: [InfoComponent],
      providers: [
          {provide: InfoService, useClass: InfoServiceStub },
      ],
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(InfoComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

   it('should create', () => {
     expect(component).toBeTruthy();
   });
});

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

Having trouble getting a Jasmine test to pass for a basic Angular2 component

Here is a snippet of my basic component setup: @Component({ selector: 'messages', styleUrls: ['messages.component.scss'], templateUrl: 'messages.component.html', }) export class MessagesComponent implements OnInit ...

The current inquiry does not conform to the MultipartHttpServletRequest format

I've been encountering an error while trying to send both an image and an object from Angular to Spring Boot. The error message I keep receiving is: Current request is not of type [org.springframework.web.multipart.MultipartHttpServletRequest] Below ...

Exploring how enums can be utilized to store categories in Angular applications

My application has enums for category names on both the back- and front-end: export enum CategoryEnum { All = 'All', Category1 = 'Category1', Category2 = 'Category2', Category3 = 'Category3', Cate ...

Encountering errors 'LeftSegment' not found and 'infer' not found within the react-router directory in the node_modules folder

Currently, I am in the process of updating my application from react-router v3 to v6. At the moment, I have successfully installed react-router-dom v6.2.1 as well as react-router v6.2. Additionally, since I am using Typescript, I have also installed @types ...

Can I use http.get() on Stackblitz to fetch a JSON data file?

One of my Angular services is structured as follows: import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable, of } from 'rxjs'; @Injectable({ providedIn: 'root ...

What are the best ways to improve the efficiency of my filtering function

Currently, I'm working on a project involving Angular, NestJS, GraphQL, and MongoDB. I have created a modal component for filtering data that contains multiple fields. However, I am not confident that the code I wrote follows best practices and am see ...

What is preventing me from consistently accessing the Type Definition while my cursor is on a JavaScript/TypeScript parameter name in VS Code, and what are some strategies I can use to overcome this issue?

Imagine I have the following code snippet in my VS Code: type T1 = { x: number }; type T2 = { x: number } & { y: string }; function foo(arg1: T1, arg2: T2) {} If I place my cursor on arg1 and go to the type definition (either through the menu or a sh ...

Does Vue.js have its own version of Angular's named templates feature?

Check out this snippet of Angular code: <ng-container *ngIf="someCondition; else spinner"> Show Data </ng-container> <ng-template #spinner> Show Spinner </ng-template> Do you know if there is a similar vue.js equ ...

Struggling to identify the error while utilizing Jasmine's throwError function

I am relatively new to using Jasmine and have been experimenting with the toThrowError() function. However, I can't seem to get my test to pass successfully. In one of my functions, I purposely throw an error: test.service.ts test(list:{}){ if ...

Combining pixijs with TypeScript in Ionic 2 using npm

To begin, I ran the command npm install -g ionic Followed by ionic start pixiApp blank --v2 Navigated to the pixiApp directory with cd pixiApp Installed necessary dependencies using npm install Added a specific version of pixi.js (4.1.0) with npm install p ...

Angular and Jest combo has encountered an issue resolving all parameters for the AppComponent. What could be causing this error?

I am currently working within a Typescript Monorepo and I wish to integrate an Angular 8 frontend along with Jest testing into the Monorepo. However, I am facing some challenges. The tools I am using are: Angular CLI: 8.3.5 My Approach I plan to use ...

How can Vue Router be integrated with Vue.JS SSR?

Despite reading up on SSR documentation, I am struggling to make it work (I feel lost). I created the project with Vue CLI using 'vue new frontend'. I opted for typescript and configured all settings in package.json. Additionally, I am utilizing ...

Experience the convenience of lazy-loading in Angular Ivy: The InjectionToken ng-select-selection-model provider is not available

Issue Description I have integrated angular's IVY compiler and lazy-loading feature according to the tutorial found here: However, when I attempt to lazy-load a module and add an instance of a component to my application, the ng-select element is not ...

What kind of data type should the value property of Material UI TimePicker accept?

While reviewing the documentation, I noticed that it mentions any, but there is no clear indication of what specific data types are supported. The value sent to the onChange function appears to be an object rather than a Date object, and in the TypeScrip ...

Unable to start Angular application, encountering errors while running ng serve

The challenge at hand As I delve into a new project, I've successfully cloned the repository onto my local machine. After utilizing npm install to fetch the necessary packages, running ng serve triggers a series of errors. Despite the application fai ...

How can one determine the completion of a chunked download request in Angular's HTTP client?

Currently, I am utilizing angular's HttpClient to retrieve an arraybuffer. The server is transmitting the data along with the following headers: *To avoid any confusion, the download route essentially retrieves a chunk file stored in the cloud. Howev ...

The Angular2 application encountered a 404 file not found error while trying to read a Const from a ts

Recently I started working with angular2 and encountered a problem when trying to access constant values from an external .ts file using the following code: import {apis} from '../constants/apis'; The content of the constants/apis.ts file is as ...

Check to see if the validator control contains the mandatory attribute

I'm working on a unique form validation directive for custom templates. Is there a way to check if the control has a required attribute? ...

The Jasmine test in my Angular project is experiencing a timeout issue, displaying the error message "Async callback was not invoked within 5000ms", despite the fact that no async function is being used in the

Reviewing the source code: import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { IonicModule } from '@ionic/angular'; import { HomePage } from './home.page'; import { LevelGridComponent } from &a ...

Revamping outdated dependencies in package.json for Angular 6

Currently, I am working with the latest version of Angular (6) and have been attempting to update my dependencies in the package.json. I was wondering if it is safe to use the npm update command to update all dependencies, or if there are other methods th ...