Error: The unit test encountered an issue as it is unable to access the property 'subscribe' of an undefined value

I'm currently troubleshooting the "should create" unit test for a component, and I keep running into this error:

TypeError: Cannot read property 'subscribe' of undefined
    at ElectionResultsChartsComponent.webpackJsonp../src/app/pages/user/election-results/election-results-charts/election-results-charts.component.ts.ElectionResultsChartsComponent.initElectionResultsData (http://localhost:9876/_karma_webpack_/webpack:/src/app/pages/user/election-results/election-results-charts/election-results-charts.component.ts:28:36)
    at new ElectionResultsChartsComponent (http://localhost:9876/_karma_webpack_/webpack:/src/app/pages/user/election-results/election-results-charts/election-results-charts.component.ts:24:10)
    at createClass (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:12481:1)
    at createDirectiveInstance (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:12326:22)
    at createViewNodes (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:13784:38)
    at createRootView (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:13673:1)
    at callWithDebugContext (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:15098:26)
    at Object.debugCreateRootView [as createRootView] (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:14381:1)
    at ComponentFactory_.webpackJsonp../node_modules/@angular/core/esm5/core.js.ComponentFactory_.create (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:11278:26)
    at initComponent (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/testing.js:1150:1)

election-results-charts.component.spec:

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

  const fakeActivatedRoute = {
    snapshot: { data: {} }
}

let mockSomeService = {
  getData: () => {}
}
const mockResultResolver = {
  initElectionResultsData: () => new EmptyObservable()
};

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        ChartsModule
      ],
      declarations: [ ElectionResultsChartsComponent ],
      providers: [
        { provide: ActivatedRoute, useValue: fakeActivatedRoute }, 
        { provide: ElectionResultsResolver, useValue: mockResultResolver },
      ]
    })
    .compileComponents();
  }));

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

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

election-results-charts.component:

export class ElectionResultsChartsComponent implements OnDestroy {

  private pieChartLabels:string[] = [];
  private pieChartData:number[] = [];
  private pieChartType:string = 'pie';

  private parties: Party[] = [];

  private subData: any;

  constructor(private route: ActivatedRoute) { 
    this.initElectionResultsData();
  }

  initElectionResultsData() {
    this.subData = this.route.data.subscribe(({ data }) => {
      let electionResultResponse: ElectionResultResponse = data;
      for(let party of electionResultResponse.parties) {
        this.pieChartLabels.push(party.name);
        this.pieChartData.push(party.voteCount)
      }
    });   
  }

  ngOnDestroy() {
    this.subData.unsubscribe();
  }

}

election-results-resolver.service:

@Injectable()
export class ElectionResultsResolver implements Resolve<any> {

  constructor(private adminService: ElectionService) { }

  resolve(route: ActivatedRouteSnapshot): Observable<any> {
    let electionRequest: ElectionRequest = {id: +route.paramMap.get('id')}
    return this.adminService.getElectionResults(electionRequest);
  }
}

This component utilizes a Routing resolver before the page loads to fetch data and then populates arrays with the fetched data.

Any suggestions on how I can address this issue? I've searched online but haven't found a definitive solution yet.

Answer №1

  1. Utilize the routing by importing the ActivatedRoute testing module into your application.

Here is an example :

import { RouterTestingModule } from '@angular/router/testing';

TestBed.configureTestingModule({
      imports: [
        ChartsModule, RouterTestingModule
      ],
....
  1. Your error may be caused by a lack of Observable return in your mock. By using the RouterTestingModule, you can eliminate this issue.

Therefore, remove the following :

{ provide: ActivatedRoute, useValue: fakeActivatedRoute },
  1. In future tests, make sure to update the data section of your route. Here's how you can do it.

Example :

Object.defineProperty(component.route, 'data', {
  writable: true,
   value: Observable.of({/* Mock the data your route will return here */});
});

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

Using the (GoogleMock) mock class as a template parameter

I have recently utilized a class that utilizes the policy design pattern and now I am looking to perform tests on it using googletest/googlemock. For instance, in the code snippet below, I want to conduct tests on class Foo and intend to use a mock class ...

Exploring within the Angular submodule path

I am facing a challenge with nested modules having different URL prefixes. I want to navigate within one module without specifying the prefix, making it accessible regardless of the prefix. Here are the routes for my app.module: const APP_ROUTES: Routes ...

Create a dynamic Prisma data call by using the syntax: this.prisma['dataType'].count()

I'm currently working on implementing a counting function that can be utilized in all of my objects. In my 'core' file, Prisma is involved in this process. This allows me to execute commands like this.user.count() or this.company.count() I ...

Setting the ariaLabel value in TypeScript is a straightforward process that involves defining the

In my TypeScript React application, I am attempting to dynamically set the ariaLabel value. However, ESLint is flagging an error: Property 'ariaLabel' does not exist on type 'HTMLButtonElement'. I have tried various types but none of t ...

What is the best way to reset the testing subject between test cases using Jest and TypeScript?

I'm currently utilizing typescript alongside jest for unit testing. My goal is to create a simple unit test, but it consistently fails no matter what I try. Below is the snippet of code in question: // initialize.ts let initialized = false; let secre ...

Using Pipe directive in Angular 2 with ES5: Error - Directive annotation missing from constructor

My simple pipe looks like this: app.DisplayKeystrokePipe = ng.core .Pipe({ name: "displayKeystroke" }) .Class({ transform: function() { } }); On the other hand, I have a more complex component/directive: app.Drop ...

Angular 6 Calendar Template issues with parsing: Unable to link to 'view' as it is not recognized as a valid property of 'div'

I am in the process of developing an application that utilizes this angular calendar. My tech stack includes Angular 6 with AngularFire2 and Firebase. Below is my app.module.ts file: import { BrowserModule } from '@angular/platform-browser'; imp ...

Issues with maintaining the checked state of radio buttons in an Angular 4 application with Bootstrap 4

In my Angular 4 reactive form, I am struggling with the following code: <div class="btn-group" data-toggle="buttons"> <label class="btn btn-primary" *ngFor="let item of list;let i=index" > <input type="radio" name="som ...

Setting up default QueryParamsHandling in Angular

I have successfully developed an angular 9 application and implemented localization using @ngx-translate. To ensure that the app changes locale based on the 'lang' query parameter, I configured it accordingly. @Component({ selector: 'app- ...

Finding a date from a calendar with a readonly property in Playwright

Just starting out with the playwright framework after working with Protractor before. I'm trying to figure out the correct method for selecting a date in Playwright. selector.selectDate(date) //having trouble with this ...

Transforming ReactJS files into TypeScript (.tsx) files

An error in TypeScript occurred while trying to convert a React project to TypeScript. Error Message: TypeScript error in /src/App.tsx(34,44): No overload matches this call. Overload 1 of 2, '(props: RouteProps | Readonly<RouteProps>): Route&l ...

Angular 4 applications do not come with TinyMCE embedded

I've been attempting to integrate the tinyMCE editor into an angular4 application, but unfortunately I encountered an error that reads: tinyMCE is not defined. https://i.stack.imgur.com/qMb5K.png I have been following the guidance provided by tin ...

The TypeScript error occurs when trying to set the state of a component: The argument 'X' cannot be assigned to the parameter of type '() => void'

When I attempt to call setState, I encounter a TypeScript error. Here is the code snippet causing the issue: updateRequests(requests: any, cb:Function|null = null) { this.setState( { requests: { ...this.state.requests, ...

What causes functions operating on mapped objects with computed keys to not correctly infer types?

If you are seeking a way to convert the keys of one object, represented as string literals, into slightly modified keys for another expected object in Typescript using template string literals, then I can help. In my version 4.9.5 implementation, I also ma ...

What is the best way to assign a variable with the type (x:number)=>{y:number,z:number}?

I am trying to initialize a variable called foo, but my current code is not compiling successfully. let foo: (x: number) => {y:number,z: number} = (x) => {x+1, x+2}; This results in the following error: Left side of comma operator is unused and ha ...

Utilizing absolute imports in Typescript directory structure

Our team has a preferred structure for organizing React code, which looks like this: components/ button.tsx slider.tsx index.ts helpers/ math.ts auth.ts index.ts constants/ config.ts api.ts index.ts In this setup, each ...

Combining React with Typescript allows for deep merging of nested defaultProps

As I work on a React and Typescript component, I find myself needing to set default props that include nested data objects. Below is a simplified version of the component in question: type Props = { someProp: string, user: { blocked: boole ...

How to dynamically set attributes for globally created components in Angular 6

In the process of developing an Angular 6 and Primeng project, I am extensively utilizing a primeng component called p-spinner. This particular component creates a native component <input type="text" along with two buttons styled with the class ui-spinn ...

Need an email verification request through firebase

Need help with sending email verification upon user sign up. Here is the code in provider/user.ts: onCreate(form: NgForm) { var user = new User(); user.name = form.value.name; user.email = form.value.email; user.contact = form.value.contact; if(form.valu ...

Evaluation of button display based on certain conditions

I currently have two different render functions that display certain elements based on specific conditions. The first render function looks like this: private render(): JSX.Element { return ( <div> {this.props.x && this.state.y ...