Issue with dependency injection not functioning during ngOnInit in Angular 7 unit testing

I am currently working with Angular 7 and Angular CLI version 7.3.4. I have a component that is being unit tested which involves injecting 2 services. Below, you will find the essential code snippets including the stub causing errors, the spec file, and the crucial part of the component in question. Despite my efforts, I keep encountering an error "TypeError: this.spreading.getSpreadingDays is not a function." I have already injected the service, so the function should be defined. I believe it's a simple mistake on my end, but even after referencing various tutorials, I can't seem to identify what's wrong with my code. Any advice or suggestions would be greatly appreciated.

Spec file

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

import { SpreadSignUpComponent } from './spread-sign-up.component';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { AuthService } from 'src/app/core/services/auth.service';
import { SpreadingService } from 'src/app/core/services/spreading.service';
import { AuthServiceStub } from 'src/app/core/testing/auth.service.stub';
import { SpreadingServiceStub } from 'src/app/core/testing/spreading.service.stub';

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

  let authService: AuthService;
  let spreadingService: SpreadingService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [
        { provide: AuthService, useValue: AuthServiceStub },
        { provide: SpreadingService, useValue: SpreadingServiceStub }
      ],
      declarations: [ SpreadSignUpComponent ],
      schemas: [ NO_ERRORS_SCHEMA ],
    })
    .compileComponents();

    authService = TestBed.get(AuthService);
    spreadingService = TestBed.get(SpreadingService);
  }));

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

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

stub class:

import { SpreadingService } from '../services/spreading.service';
import { of } from 'rxjs';
import { SpreadingDay } from 'src/app/shared/models/spreadingDay';
import { I } from 'src/app/shared/testing/interfaceBuilder';

export class SpreadingServiceStub implements I<SpreadingService> {

  getSpreadingDays() {
    return of([]);
  }

  getSpreadingDaysForUser() {
    return of([]);
  }

  setSpreadingDay(
    spreadingDay: SpreadingDay
  ) {
    return <Promise<void>>{};
  }

  addVolunteerToDay(
    spreadingDay: SpreadingDay,
    userID: string,
  ) {
    return <Promise<void>>{};
  }

  removeVolunteerFromDay(
    spreadingDay: SpreadingDay,
    userID: string,
  ) {
    return <Promise<void>>{};
  }

  addRequestToDay(
    spreadingDay: SpreadingDay,
    userID: string,
    first: string,
    last: string,
  ) {
    return <Promise<void>>{};
  }
}

component:

import { Component, OnInit } from '@angular/core';
import { SpreadingService } from 'src/app/core/services/spreading.service';
import { SpreadingDayReturn, SpreadingDay } from 'src/app/shared/models/spreadingDay';
import { Observable } from 'rxjs';
import { AuthService } from 'src/app/core/services/auth.service';

@Component({
  selector: 'app-spread-sign-up',
  templateUrl: './spread-sign-up.component.html',
  styleUrls: ['./spread-sign-up.component.scss']
})
export class SpreadSignUpComponent implements OnInit {

  spreadingDays$: Observable<SpreadingDayReturn[]>;

  constructor(
    private auth: AuthService,
    private spreading: SpreadingService,
  ) { }

  ngOnInit() {
    this.spreadingDays$ = this.spreading.getSpreadingDays();
  }

Answer №1

Within your code snippet

{ provide: SpreadingService, useValue: SpreadingServiceStub }
, it appears that the correct syntax should be
{ provide: SpreadingService, useClass: SpreadingServiceStub }
. This mistake may be easily overlooked. I presume the same correction should also be made for the second service stub.

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

Applying a Typescript Generic to enhance the functionality of the API fetcher

I've written a simple function to enhance fetch functionality. I am currently exploring how TypeScript Generics can be utilized to define the Type for 'data' in the return. const apiFetchData = async ( url: string, options = {}, ): P ...

How can I use Angular 2 npm start to forward API requests to a different server?

Is there a way to redirect my AJAX requests to another server by using npm start? When attempting npm start --proxy http://localhost:8080, it does not seem to function as intended. ...

The 'any' type is automatically assigned to Angular and Element since the type 'IData' lacks an index signature

Looking to display specific object properties based on predefined keys in an array? Here's an example using TypeScript: const dataObject: IData = { a: 1, b: 2, c: 3 }; const dataKeys: string[] = ['a', 'c']; dataKeys.forEach((key: ...

Navigating through a multidimensional array in Angular 2 / TypeScript, moving both upwards and downwards

[ {id: 1, name: "test 1", children: [ {id: 2, name: "test 1-sub", children: []} ] }] Imagine a scenario where you have a JSON array structured like the example above, with each element potenti ...

Seeking guidance on integrating angular2 dependency injection with value providers - any advice would be appreciated!

After following the angular documentation on Dependency Injection and attempting to replicate the section on dependency injection tokens, it's evident that I am still struggling to grasp the concept. My goal is to utilize a value provider to inject a ...

Can you explain the meaning of this TypeScript code snippet?

interface Configuration { [input: string]: any; } This is really puzzling to me, the 'input' is declared as a string type with any value? Appreciate your help. ...

Placeholder text in Angular Material Input field not being dynamically updated

Currently, I am utilizing Angular 6 along with Material CSS obtained from material.angular.io My objective is to develop a directive that facilitates translation. <span translate>page.login.btnsubmit</span> The above code successfully transl ...

ngclass is not functioning properly when used with dynamically generated components

I am experiencing an issue with the components I create using createComponent. Although some of them function properly, others lack the appropriate CSS classes. Despite using a function and [ngClass] to set the classes, they do not appear when inspected in ...

Do I need to include JQuery along with Bootstrap when using Angular?

It has come to my attention that for interactive event-driven elements such as clicking, hover effects, modals, etc. in Bootstrap, we typically require JQuery. Are there any other options available that would allow us to bypass the need for JQuery when i ...

Error: Module not found - Unable to locate 'dropzone'

Since migrating from Angular 4.4 to Angular 8.0, I encountered the following issue: ERROR in ./src/attributes/import/import.component.ts Module not found: Error: Can't resolve 'dropzone' in 'C:....\src\attributes\imp ...

What is the best way to incorporate an interface in TypeScript that is both callable and has properties?

Given the scenario where an interface is defined as: interface FooWithBar { ():void; bar():void; } I am struggling with writing the implementation. I attempted the following: function foo(){ } foo.bar = function(){ }; This approach did not wo ...

Preserving the value of a function argument for future reference

I have a function called myFunction() that accepts one argument. My goal is to save this argument to a variable and be able to access it later. Here is what I am attempting to do: When a user performs an action, an event is passed as an argument to the m ...

How to open a print preview in a new tab using Angular 4

Currently, I am attempting to implement print functionality in Angular 4. My goal is to have the print preview automatically open in a new tab along with the print popup window. I'm struggling to find a way to pass data from the parent window to the c ...

The NgRX Effect is malfunctioning

Working on integrating ngrx with Angular. Authentication is successful, but facing issues with product store implementation: Organizing the project using modules: const routes: Routes = [ { path: '', redirectTo: 'home', ...

The shop named 'someStore' is currently unavailable! Please ensure that it is being offered by a valid Provider

I'm having trouble setting up a new project using React, Typescript, and MobX. Despite having a relatively simple piece of code, I can't seem to get MobX to work properly. It keeps showing me this error message: Uncaught Error: MobX injector: S ...

Validating Angular Forms within a NgFor loop

Consider the scenario where there is a form implemented as shown below: <form #form="ngForm"> <div *ngFor="let action of member_plan.actions"> <div class="container"> <h4 class="text-sm-center black mb-3">{{ ...

Troubleshooting ASP.NET MVC Core 2 and Angular 5 for Beginners: Component Display Issue Resolved with App-Root

Currently, I am facing an issue while trying to set up a simple ASP.NET Core 2 & Angular 5 web application. The problem arises when a component fails to display unless the app-root component is also included. The issue manifests when I add the app-root in ...

Utilize the global theme feature within React Material-UI to create a cohesive

I'm feeling a bit lost when it comes to setting up React Material-UI theme. Even though I've tried to keep it simple, it's not working out for me as expected. Here is the code snippet I have: start.tsx const theme = createMuiTheme({ ...

What is the process for including an optional ngModelGroup in Angular forms?

I'm encountering an issue with incorporating the optional ngModelGroup in angular forms. Although I am familiar with how to use ngModelGroup in angular forms, I am struggling to figure out a way to make it optional. I have attempted to pass false, nu ...

Can you explain the TypeScript type for the queryKey in React Query?

Currently utilizing react query in conjunction with typescript. What should be the type of arguments passed to the function? export const useIsTokenValid = () => { const { data: token } = useQuery<string | null>(['token'], getToken, { r ...