Tips for monitoring/faking method invocations within an Angular 5 service's constructor

My service involves making 2 method calls in the constructor:

  constructor(private http: HttpClient) {
    this.apiURL = environment.apiURL;
    this.method();
    this.method2().subscribe();
  }

I am facing difficulties testing this service in the TestBed. I'm unable to spyOn using Jasmine's spies before calling TestBed.get(MyService).

Below is my Service's configuration for the TestBed:

  let myService: MyService;
  let backend: HttpTestingController;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientModule,
        HttpClientTestingModule
      ],
      providers: [
        MyService
      ]
    }).compileComponents();

    myService = TestBed.get(MyService);
    backend = TestBed.get(HttpTestingController);

How can I properly spyOn method() and method2() and return a value for them? Is it not recommended to include methods in the constructor of a Service?

method() and method2() make an HTTP call to the server to "refresh" user data, such as Posts on a wall. Another method involves an Observable.timer that auto signs out the app once the token expires.

Answer №1

When method and method2 are prototype methods, they can be spied on the class prototype like this:

it('', () => {
  spyOn(MyService.prototype, 'method').and.callThrough();
  spyOn(MyService.prototype, 'method2').and.callThrough();
  const svc = TestBed.get(MyService);
  expect(svc['method']).toHaveBeenCalled();
  expect(svc['method2']).toHaveBeenCalled();
});

The suitability of using these methods in the constructor depends on their behavior.

If a method returns a subscription, it should be stored as a property to allow for unsubscribing later, such as during service destruction.

Given that method and method2 are asynchronous, calling them in the constructor could lead to issues. If these methods trigger requests that are expected to be completed upon service instantiation, there may be a race condition because the requests have not finished and the service does not offer a way to track their status through a promise or observable. The recommended approach is to call them at a more suitable time for asynchronous provider initialization, such as within APP_INITIALIZER or a route resolver.

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

Issue with Vue @Watch not properly recognizing changes in a boolean value

I'm currently experimenting with watch functions in vue-ts. I have configured a watch function that is supposed to trigger whenever a Boolean variable's value changes, but for some reason, it's not triggering at all and I'm unable to de ...

Is there any re-rendering optimization feature in Angular 2?

After experimenting with React for a few months, I've noticed that it doesn't just re-render a component entirely. Instead, it identifies the differences and updates only those parts. Does Angular 2 operate in a similar manner? Additionally, whe ...

Sending environmental variable values to an Angular application from a Docker file

I am currently facing a challenge with my Angular application where I am attempting to define the environment variable from an external source, specifically from a docker compose file. For reference, I found an article that addresses this issue: docker-c ...

Combine Sonarqube coverage with Istanbuljs/NYC for enhanced code analysis

In my typescript project, we utilize a Jenkins pipeline to run all functional tests in parallel after building the main container. Towards the end of the pipeline, we conduct a code coverage check and then transfer the results to sonarqube. Below is an ex ...

How can Angular 4 manage an object containing other objects most effectively?

Who can guide me on the best way to handle a data structure like this: { "1":{ "id":"1", "name":"Facebook", "created_at":"", "updated_at":"", "fields":{ "1":{ "id":"1" ...

Leveraging an external TypeScript library in a TypeScript internal module

Imagine you find yourself in a situation where you need to utilize a typescript/node library within an internal module that is spanned across multiple .ts files. ApiRepositoryHelper.ts import * as requestPromise from "request-promise"; module ApiHelp ...

Introducing the Angular 2/4 Dashboard Widget Module!

I am currently developing the dashboard for my Angular 2 application and I am in search of an npm package that fits my requirements. I came across a link that provides similar functionalities to what I need, which is . I want to be able to add new w ...

Disappearance of Current User in Console When Refreshing Angular 4/5 Firebase

After creating an Angular 5 login using Firebase, I noticed an issue with the authentication object disappearing upon page reload. Even though the user remains logged in, the auth object vanishes once the page is refreshed (the username is still displayed ...

An issue arises following an upgrade in Angular from version 9 to version 10, where the property 'propertyName' is being utilized before it has been initialized

I've spent time looking on Google, Github, and Stackoverflow for a solution to this error, but I'm still struggling to fix it. Can anyone offer a suggestion or help? Recently, I upgraded my Angular project from version 9 to version 10, and after ...

"Enhance your software with a customizable interface or develop new functionalities to generate analogous

Having API data with a similar structure, I am looking to streamline my code by filtering it through a function. However, as someone new to TypeScript, I am struggling to implement this correctly using a function and an interface. Essentially, I aim to ach ...

My code is ready, but unfortunately, it is not retrieving the data as expected from my JSON file

I'm encountering an issue with my code where it's not fetching data from my JSON file. I keep getting 0 arguments and I'm unsure of what I'm doing wrong. Can someone provide assistance? This project is built using Angular. I have my ...

Listening for Angular 2 router events

How can I detect state changes in Angular 2 router? In Angular 1.x, I used the following event: $rootScope.$on('$stateChangeStart', function(event,toState,toParams,fromState,fromParams, options){ ... }) In Angular 2, using the window.addEv ...

Error with declaring TypeScript class due to private variable

When defining a TypeScript class like this: export class myClass { constructor(public aVariable: number) {} private aPrivateVariable: number; } and trying to initialize it with the following code: let someVar: myClass[] = [{ aVariable: 3 }, { aV ...

Sharing data between parent and child components in Angular using ngrx

Currently, I am implementing @ngrx router and facing a scenario where one of the routes includes child routers for passing route parameters. Here is how it looks: { path: '/browse', component: BrowseComponent, children: [ { path: ':ca ...

The specified property is not recognized by the type in TypeScript

I have set up a basic form with validation in Ionic 2. The form functioned properly when I used 'ionic serve' but encountered issues when running 'ionic run'. My suspicion is that the problem lies within my TypeScript code, specifically ...

Mastering the art of navigating through intricate nested properties within JSON data structures

Presented below is a dynamic JSON structure: data = { "name": "deltha", "type": "object", "important": [ "name", "id", "number" ], "information": { "place": { "editable": false, "visible": true }, "info": { ...

Tips for creating a tailored Express.js request interface using Typescript efficiently

I have been working on designing a custom Express request interface for my API. To achieve this, I created a custom interface named AuthRequest, which extends Request from Express. However, when attempting to import my interface and define req to utilize t ...

Tips for tracking the evolution of changes to an array within React State

Experiencing challenges with saving the history of updates and modifications on a State. I have an object called "Journey" which includes a list of workshops (another array). Whenever I update my list of workshops, I aim to create a new array that captures ...

The Angular2 view is failing to display updated data from a shared service

I've been struggling to show data from my shared service, but it's not displaying. Can someone please help me out? I've been stuck on this for the past few days. I've tried NgZone and ChangeDetectorRef, but they haven't worked for ...

Tips for deleting on a numeric cell within ag-grid?

While exploring the functionality of AG-Grid with the example provided at this link [, I am currently experimenting with the numeric editor feature. I found this example on the official AG-Grid website [https://www.ag-grid.com/javascript-grid-cell-editor/ ...