Mastering unit testing with Behaviour Subjects in Angular

I am looking to test the get and set methods of my user.store.ts file. The get() method is used to retrieve users, while addUsers() is utilized to add new Users to the BehaviorSubject. How can I accomplish this?

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { User } from 'ngx-login-client';

@Injectable({
  providedIn: 'root'
})

export class UserStore {

  private _users: BehaviorSubject<User[]> = new BehaviorSubject([]);

  get users() {
    return this._users.asObservable();
  }

  addUsers(users: User[]) {
    this._users.next(users);
  }
}

I expect that values will be added when addUsers() is called, and I can retrieve users by calling get users(). I am relatively new to Angular Testing.

An error message similar to the following has been appearing:

Expected Observable({ _isScalar: false, source: BehaviorSubject({
  _isScalar: false, observers: [  ], closed: false, isStopped: false, hasError: false, thrownError: null, _value: [ Object({ attributes:
  Object({ fullName: 'name', imageURL: '', username: 'myUser' }), id:
  'userId', type: 'userType' }) ] }) }) to equal [ Object({ attributes:
  Object({ fullName: 'name', imageURL: '', username: 'myUser' }), id:
  'userId', type: 'userType' }) ].

The structure of my User[] object is as follows:

{
    'attributes': {
        'fullName': 'name',
        'imageURL': '',
        'username': 'myUser'. 
    },
    'id': 'userId',
    'type': 'userType'
}

Update: My user.store.spec.ts file.

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

import { UserStore } from './user.store';
import { BehaviorSubject } from 'rxjs';
import { User } from 'ngx-login-client';

describe('UsersStore', () => {
  beforeEach(() => TestBed.configureTestingModule({}));

  it('should be created', () => {
     const store: UserStore = TestBed.get(UserStore);
     expect(store).toBeTruthy();
  });
  it('should add Users', async(() => {
    let store: UserStore;
    store = TestBed.get(UserStore);
    let user: User[];
    const testUser: User[] = [{
      'attributes': {
      'fullName': 'name',
      'imageURL': '',
      'username': 'myUser'
    },
    'id': 'userId', 
    'type': 'userType'
   }];
   store.addUsers(testUser);
   store.users.subscribe(users => {
     expect(users).toBe(testUser);
     });
  }));
});`

Answer №1

As mentioned in the error message, the provided data is Observable while your test scenario expects an Object.

To rectify this issue, you should structure your test case as follows:

it('should retrieve users', async(() => {
  component.users.subscribe(users => {
    fixture.detectChanges()
    expect(users).toBe(testUsers)
  })
}))

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

Vue version 3 is encountering an issue with a module that does not have an exported member in the specified path of "../../node_modules/vue/dist/vue"

After I updated my npm packages, errors started popping up in some of the imports from the 'vue' module: TS2305: Module '"../../node_modules/vue/dist/vue"' has no exported member 'X' The X instances affected inclu ...

How to access the result without using subscribe in Angular?

I am facing unexpected behavior with a method in my component: private fetchExternalStyleSheet(outerHTML: string): string[] { let externalStyleSheetText: string; let match: RegExpExecArray; const matchedHrefs = []; while (match = this.hrefReg.exe ...

The input in the schema fails validation against the Angular 7 schema with the following data: {"name":"testng7"}

After updating the Angular CLI to the latest version on my Mac OS, I encountered an issue when trying to create a new project using the command ng new testng7. The error message displayed was: Schematic input does not validate against the Schema: {"na ...

Using a custom jQuery function within an Angular component class

I have a custom query function that I wrote in a JavaScript file located under the source folder (/src/assets/inlineedit.js) of my Angular application. Here is the content of the file: $.fn.inlineEdit = function(replaceWith, connectWith) { $(this).ho ...

Unable to push items to an array in Angular

I am currently working with a Java service that retrieves data from an Oracle database. The goal is to display the results in an Angular application using an array of objects: resultSet:Info[]=[]; Here is the code for the service: pastHourInfo() { ...

When adding new elements to an array, the IDs of all objects become identical

When running the code below: dietDay.meals.forEach((meal) => { meal.mealProducts.forEach((mealProduct) => { if ( mealProduct.product.id && this.fetchedProductIds.includes(mealProduct.p ...

Transform a list of time slots into a time interval using Angular (2/4/5/6)

Hello everyone! Just wanted to share my updated solution after considering your feedback. Thank you! getTime(apptTime) { const fields = apptTime.split("-"); const startingTime = this.formatTime(+fields[0]); const endingTime = this.formatTime(+fie ...

Guide to implementing asynchronous REST API requests in Ionic 2

I'm working on an app for a school that allows students to scan their ID cards and enter. On the teacher's side of the application, I display the number of students present in each class. Currently, I am using a refresher to reload the page and u ...

I would like my division to split into two halves, each with a width of 50%, and be aligned next to each other using fxLayout

<div fxLayout="row" fxLayoutAlign="space-between" style="background-color: blue;"> <div fxLayout="column" style="width: 50%;">1stOne </div> <div fxLayout="column" styl ...

Specifying the type of "this" within the function body

After going through the typescript documentation, I came across an example that explains how to use type with this in a callback function. I am hoping someone can assist me in comprehending how this callback will operate. interface DB { filterUsers(fil ...

Is it possible to implement drag and drop functionality for uploading .ply, .stl, and .obj files in an angular application?

One problem I'm facing is uploading 3D models in angular, specifically files with the extensions .ply, .stl, and .obj. The ng2-upload plugin I'm currently using for drag'n'drop doesn't support these file types. When I upload a file ...

Upgrade Challenge from Angular 7 to Angular 9

I am currently in the process of upgrading my application from version 7 to version 9. However, I have encountered an issue with the new IVY compiler in Angular 9 not being compatible with the library angular-webstorage-service, resulting in the following ...

Top method for continuously updating the position of DOM elements in Angular 2

Currently, I am in the process of developing a game using Angular (version 4). I understand that direct manipulation of the DOM is typically not recommended when working with Angular. However, for the particular functionality I'm trying to achieve, I& ...

Tips for refreshing a React component using incremental changes retrieved from an API

I am developing a unique React application using Next.js and TypeScript, with an api-backed data set in one component that needs to be cached indefinitely. Unlike traditional examples I have found online, my component must: Fetch only the most recent 100 ...

Develop a binary file in Angular

My Angular application requires retrieving file contents from a REST API and generating a file on the client side. Due to limitations in writing files directly on the client, I found a workaround solution using this question. The workaround involves crea ...

Bypassing disputes in a TypeScript function

I attempted to implement the solution provided by Pacerier in response to the question about skipping arguments in a JavaScript function. However, it doesn't seem to be working for me. The function I am dealing with has numerous arguments. this.servi ...

Pagination problem arises when sorting through items

I am facing an issue with filtering items on different pages of my React website. The problem I encounter is that the filtering functionality only works on the initial page where the data is loaded. Code: CustomersEpolicyPage.tsx import React, {useEffect ...

Disable the yellow curly error lines in Visual Studio Code

Currently, I am utilizing VSCode with ESlint for Typescript development. I'm curious about how to turn off or remove the yellow curled error lines in my code editor, like the ones displayed in this example image: https://i.stack.imgur.com/Zdtza.png M ...

Unforeseen results arise when using the ng-if directive on a DIV element within an Angular context

@angular/upgrade/static Attempting to upgrade an AngularJS controller to Angular context using UpgradeModule from '@angular/upgrade/static' Encountering issues when changing ng-show to ng-if on span or div elements, as the enclosed content does ...

Exploring Angular RxJS: the art of filtering Observable arrays

Is there a way to effectively filter an array Observable in Angular? I am working with an observable Array: announcementList$: Observable<Announcement[]> = this.announcementService.getAnnouncement(0,0).pipe(filter(Boolean),shareReplay(), map(({data} ...