Ways to mimic an Angular subscription during a Jasmine test

I'm currently troubleshooting a unit test for my code (I'm not very experienced with Jasmine) after adding some subscriptions to a service. I'm encountering an issue where the subscriptions are coming up as undefined. I'm not entirely sure about the correct way to include these subscriptions.

Here is a simplified version of my component:

export class AppComponent implements OnInit, AfterViewInit {
  isSignedIn = false;
  isLoggedIn = false;
  signedInSubscription: Subscription;
  loggedInSubscription: Subscription;

  constructor(
    private authenticationService: AuthenticationService,
    private router: Router,
    private http403Tester: Http403TestService,
  ) {
    this.isLoggedIn = authenticationService.isLoggedIn;
    this.isSignedIn = authenticationService.isSignedIn;
    this.setEnvironment();
  }

  async ngOnInit() {
    // line 69 below, this is where the error is
    this.signedInSubscription = this.authenticationService.observableIsSignedIn.subscribe(item => {
      this.isSignedIn = item;
    });
    this.loggedInSubscription = this.authenticationService.observableIsLoggedIn.subscribe(item => {
      this.isLoggedIn = item;
    });
  }  
}

The service:

export class AuthenticationService {
  constructor() {
    this.observableIsSignedIn = new BehaviorSubject<boolean>(this.isSignedIn);
    this.observableIsLoggedIn = new BehaviorSubject<boolean>(this.isLoggedIn);
  }

  isSignedIn: boolean = null;
  isLoggedIn: boolean = null;
  observableIsSignedIn: any;
  observableIsLoggedIn: any;

The spec:

describe('AppComponent', () => {
  let authenticationService: any;
  let http403Tester: any;
  let router: any;
  let component: AppComponent;

beforeEach(() => {
  authenticationService = {
    isSignedIn: jasmine.createSpy(),
    isLoggedIn: jasmine.createSpy(),
    observableIsSignedIn: jasmine.createSpy(),
    observableIsLoggedIn: jasmine.createSpy(),
  };
  router = { navigateByUrl: jasmine.createSpy() };
  http403Tester = { isAuthenticated: jasmine.createSpy() };
  component = new AppComponent(authenticationService, router, http403Tester);
});

describe('ngOnInit()', () => {
  it('should navigate to /unauthorised when a 403 status code is returned', async () => {
  // Arrange
  http403Tester.isAuthenticated.and.returnValue(false);

  // Act
  await component.ngOnInit();

  // Assert
  expect(router.navigateByUrl).toHaveBeenCalledWith('/unauthorised');
});

And the error:

TypeError: Cannot read property 'subscribe' of undefined
at AppComponent.<anonymous> (src/app/app.component.ts:69:83)

It seems like using createSpy() is not the correct method for mocking a subscription:

observableIsSignedIn: jasmine.createSpy()

However, I am unsure of the next steps to take or what resources to look into. Any suggestions?

Answer №1

Give this a try

 authService = {
    isUserLoggedIn: jasmine.createSpy(),
    isAuthenticated: jasmine.createSpy(),
    userLoggedInObservable: new BehaviorSubject<boolean>(undefined).asObservable(),
    userAuthenticatedObservable:  new BehaviorSubject<boolean>(undefined).asObservable(),
  };

For additional information : Mocking a BehaviourSubject in a component test spec

Update:

You may need to double check the setup for unit testing. please refer to: https://angular.io/guide/testing#component-dom-testing

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

Where's the tsconfig.json for Firebase Emulators?

I've encountered an issue with my Firebase project that's written in JavaScript (not TypeScript). When attempting to run the functions emulator, I'm getting the following error: $ firebase emulators:start --only functions ⚠ functions: Ca ...

Using Typescript: accessing all properties from a specified type while excluding one

Currently working in React, I am interested in extending my type from another, with the exception of some props. This is how I want to approach it : import React from 'react'; import { withTheme } from 'styled-components'; import SvgBa ...

Exploring how process.argv in NodeJS can be utilized within JavaScript code compiled by

I'm having trouble compiling a basic TypeScript file using webpack (with 'awesome-typescript-loader') that needs to access command line arguments. It seems like the compiled JavaScript is causing a problem by overriding the Node 'proce ...

What are the steps to creating a comprehensive bootstrap using Angular 2?

I recently stumbled upon an interesting article discussing the integration of Angular 2 components with Drupal as a backend service. If you're curious, you can read the full article here: In the article, Matt explains how to achieve this integration ...

Encountering trouble installing Angular CLI on MacOS High Sierra version 10.13.2

I am encountering an issue while trying to install Angular CLI. I have successfully installed the latest NodeJs version 8.9.4 and npm version 5.6.0. However, when I attempt to run the command npm install -g @angular/cli, I receive the following error messa ...

What methods are recommended for implementing changes in a TypeScript library throughout the development process?

When working on a TypeScript library that is utilized as a dependency by other libraries or applications, how can I efficiently handle frequent updates without going through the process of incrementing the version number, publishing it to an NPM registry, ...

ngModel not refreshed in ng-pick select directive

Within my code, I am utilizing the ng-select component which is initially set up in the following HTML format. <ng-select id="SelectType" placeholder="Student" [multiple]="true" [items]="students" groupBy="type" [selectableGroup]="false" ...

Cannot see the template on the Angular Typescript component

After encountering and resolving this issue: AngularJS directive not displaying the template I decided to experiment with an Angular component and TypeScript, but unfortunately, I can't seem to make it work. The component refuses to display. This is ...

Issues with the functionality of Angular and Material's multi-level menu and breadcrumb integration

Currently, I am working on a project using Angular 6 and Angular Material 6. I am attempting to create a multilevel menu with breadcrumb functionality. While I have successfully implemented the multilevel menu, I am facing an issue with navigating the menu ...

Angular Form Validations - input values must not match the initial values

These are my current reactive form validations: ngOnInit(): void { this.userForm = this.formBuilder.group({ status: {checked: this.selectedUser.status == 1}, username: [this.selectedUser.username, [Validators.required, Validators.minLeng ...

Angular mat-icon can render intricate pictures

Embarking on my journey with Angular, I have recently delved into the world of mat icons. While I have managed to create simple mat icons successfully, I find myself stumped when attempting to tackle more intricate designs. Take for instance the image belo ...

Challenges arise when integrating Angular with Firebase, particularly in the realms of authentication and user

Currently, I am working on a project using Angular and Firebase. However, in the auth.service.ts file, Visual Studio Code is not recognizing the imports for auth and User. import { auth } from 'firebase/app'; import { User } from 'fireba ...

Efficiently load Angular modules only when needed on different routes

My Angular project utilizes lazy loading for modules and below are the defined routes: { pathMatch: 'full', path: '', loadChildren: () => import('./pages/landing/home-page/home-page.module').then(m => m.Hom ...

The functionality for handling gestures on AgmMap appears to be non-functional

I am currently using the AGM Map feature available on and I need to disable the zooming functionality when scrolling. Despite setting gestureHandling = "'cooperative'", it does not seem to work. Are there any specific factors causing this issue? ...

Looping through child components in Angular 2 to extract values from their content

Attempting to iterate through child components within a parent component in Angular 2 as shown below: <segment-header> </segment-header> <segment-content *ngFor="let content of listContent"> </segment-content> Where listContent is ...

Angular 4: Utilizing reactive forms for dynamic addition and removal of elements in a string array

I am looking for a way to modify a reactive form so that it can add and delete fields to a string array dynamically. Currently, I am using a FormArray but it adds the new items as objects rather than just simple strings in the array. Here is an example of ...

Leverage the power of forkJoin alongside activatedRoute

One of the observables I'm working with is the following: formData$ = forkJoin([ this.httpService.getProgramsLevelsList(), this.httpService.getProgramsTypesList(), this.httpService.getQuestionnaireReasonsList() ]).pipe( tap((res: any) => ...

Guide on importing a custom CSS file from Syncfusion Theme Studio into an Angular project

Is there a way to incorporate custom scss files downloaded from Syncfusion Theme Studio into Angular CLI without adding the URL to the styles section in angular.json? Can we directly import it into styles.scss instead? I attempted to do so by including th ...

Comparing JSON import methods: HTTP vs require

I discovered two methods for importing local json files into my code. Using angulars http get. This method is well-known for loading json input. It provides the flexibility to easily switch between remote and local json files. Typescript require Anot ...

`Is it possible to integrate npm libraries with typescript and ES6?`

I am looking to focus on using ES6 as the output for a node server-side app that I plan to run on the cutting-edge iojs distribution, which hopefully has support for the latest ES6 syntax. However, I'm unsure about how to integrate standard NPM libra ...