Creating a new instance of a class is not allowed once you have already instantiated it using Jest test

Challenge

Encountering a problem where creating a new instance of a class within a unit test does not invoke the constructor.


Specifics

Attempting to validate if an error is raised when an incorrect server IP is provided, however, generating a new object of the class responsible for throwing the error does not yield the expected outcome.

The class under scrutiny is as follows:

export class ClassA {
    private readonly _redisServerIP = config.redisServerIP;
    private readonly _redisServerPort = config.redisServerPort;

    constructor() {
        console.log(this._redisServerIP);
        this.configure();
    }

    private configure(): void {
        this._redisSub = redis.createClient({host: this._redisServerIP, port: this._redisServerPort});

        this._redisSub.on('error', (error) => {
            if (error.code === "ECONNREFUSED") {
                this._logger.error('Could not create a redisSub, is the redis server running?');
            }
            throw new Error('Something bad happened');
        });
    }
}

This represents my testing code:

import * as constants from '../src/config/config';

let socket;
let classA;
let httpServerAddr;

beforeAll((done) => {
classA = new ClassA();
    httpServerAddr = classA.getServerIp();
    done();
});

afterAll((done) => {
    done();
});

beforeEach((done) => {

});

afterEach((done) => {
    done();
});

describe('Socket.io redis testing', () => {
    test('should fail due to invalid serverIP', () => {
        constants.config.redisServerIP = "0.0.0.0";
        classA = null;

        expect(() => {
            classA = new ClassA();
        }).toThrow();
    });
});

Only one instance of the server IP appears in my node console and the test fails with the following message:

expect(function).toThrow(undefined)
Expected the function to throw an error.
But it didn't throw anything.

Is this occurring because each test operates within its own promise? Could it be related to not clearing the existing instance of ClassA before initiating a new one?

======UPDATE======

Upon using breakpoints, I have discovered that the constructor does execute, but the log statement doesn't appear. The 'throw' statement never executes either. In the case of Redis, when an error occurs, an event named "error" is sent to the server, which doesn't seem to trigger during the test run. How can one wait for this event to be triggered?

Answer №1

To solve the issue at hand, I made the redisSub public and included a process.exit(); call in case the connection failed. In my unit-test, I used spyOn to monitor process.exit() and verify if it was triggered.

Below is the test code snippet:

describe('Socket.io redis testing', () => {
    test('should fail due to invalid serverIP', () => {
        const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});

        constants.config.redisServerIP = "127.312.12.1";

        classA.stopServer();
        classA = null;
        classA = new ClassA();

        classA.redisSub.on('error', () => {
            expect(mockExit).toHaveBeenCalledWith(1);
        });
        mockExit.mockRestore();
    });

While utilizing events within ClassA could have been an alternative approach, I found directly handling the process exit more efficient in this scenario.

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

Converting Http Client GET response into an array of objects with specified type

I have a model set up for the data I am retrieving through a GET request, and my goal is to map this data to an array of Player objects. This is an example of the response data received from the API: [ { Id: 1 PlayerName: "Dave", ...

Tips for retrieving data sent through Nextjs Api routing

Here is the API file I have created : import type { NextApiRequest, NextApiResponse } from 'next/types' import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() export default async function handler(req: NextApi ...

Injecting class names into styled components while typing

Can someone assist me in correcting my code? I am trying to add class names to styled components using a custom function. Here is what I have: type IntrinsicElementsKeys = keyof { div: any, a: any } /* could be keyof JSX.IntrinsicElements */ export funct ...

What should be the proper service parameter type in the constructor and where should it be sourced from?

Currently, I am faced with a situation where I have two Angular 1 services in separate files and need to use the first service within the second one. How can I properly type the first service in the constructor to satisfy TypeScript requirements and ensure ...

How to Properly Convert a Fetch Promise into an Observable in Ionic 5 using Typescript?

I'm in the process of transitioning my Ionic3 app to Ionic5 and currently working on integrating my http requests. I previously utilized angular/http in Ionic3, but it appears that it has been deprecated. This was how I handled observables in my code: ...

Setting up tsconfig.json to enable support for either string literals or string templates involves adjusting the compiler options

After utilizing swagger codgen with the typescript-aurelia template to create API code, I noticed that a significant amount of string literals were being used in the resulting code. Despite encountering errors when running the transpiler tsc from the comma ...

Automatic type inference in function parameters in Typescript

When attempting to infer the type of Data based on input parameters, it correctly infers when the data is an object type; however, it defaults to 'unknown' when the data is a function type. https://i.sstatic.net/wkuQa.png declare function getType ...

The Angular checked functionality is not working as expected due to the presence of ngModel

Just getting started with Angular here. I’m working on a checkbox table that compares to another table and automatically checks if it exists. The functionality is all good, but as soon as I add ngModel to save the changes, the initial check seems to be ...

Having trouble running asynchronous tests for Node.js Rest API with Mocha and Chai's GET request functionality

Thank you for taking the time to read this! I've been having trouble with my testing even after researching examples and tutorials. My tests aren't working, and I'm unsure if it's a problem with Chai or my API server. All of the code ...

Using a pipe filter to implement a search feature in an Ionic search bar

Hey everyone, I'm facing a little issue here. I created a pipe filter to sort through some data, but now I need to include two more filters and I'm not sure how to go about it within this pipe. Below is an example of the pipe I have created: ...

Webpack converts 'import' statements to 'require'

I'm currently in the process of compiling my nodeJS project using webpack. Everything seems to be working correctly after compilation, but I've noticed that the imports are being changed to requires. This causes an error when trying to run index. ...

Error: The property 'create' of undefined cannot be read (Material UI/enzyme)

When I mount a component, I encounter an error that does not occur when using shallow rendering. The specific error is: TypeError: Cannot read property 'create' of undefined at stylesOrCreator (node_modules/@material-ui/core/CircularProgress/C ...

Two-way conditional type mapping

Currently, I am working on mapping the various "data types" of an object to a corresponding "schema" type. If the property's data type is boolean, it should be mapped to the "BooleanComponents" type The code snippet below demonstrates how this can ...

The significance of zone.js and rxjs within the context of Angular 2

As a newcomer to Angular2, I recently learned about zone.js and rxjs. I'm curious to know if they both serve the same purpose for handling asynchronous tasks, or if each has its own specific role. Can someone explain to me the exact reasons why zone.j ...

Visual Studio fails to acknowledge changes made to TypeScript files and incorrectly assumes that the project is up to date

I am currently utilizing TypeScript in a project based on ASP.NET Core 3 (preview 5), using the latest version of VS 2019 16.1.1 (tsc: 3.4). Whenever I perform a "Rebuild All" or make changes to any C# files or even modify the tsconfig.json file, all my T ...

Invoking a TypeScript function using a dynamically named variable

Currently, I am developing an Ionic2 app and encountered a situation where I need to call a function from a Page. I was wondering if it is possible to use a variable name in the function call. For example: Original code: this._userDataService.getGrandQues ...

The call stack has reached its maximum size while attempting to patch a value to a form control

Whenever I try to patch a value to a form control after selecting the "select all" checkbox in a multi-select drop-down menu, an error message saying "Maximum call stack size exceeded" appears when I deselect all the options. <mat-select [formControl]= ...

Using the react-select component with typescript in your project

I've been attempting to implement the Select component from react-component using TypeScript, but I encountered some overload errors. Here is a snippet of my code: type SelectedProps = { name: string; label: string; placeholder: string; readOn ...

A guide for finding a specific string within a subset of an array

I have an array containing various substrings, and I want to pass if at least one of those substrings contains the specific value I am searching for. Value1 = [ "Grape | 100 |Food Catering Service", "Apple | 100,000m |Food Catering Servi ...

Merging two arrays of objects from the same response in JavaScript

How can I efficiently merge two arrays of objects from the same response? let data = [{ "testLevel":"mid", "testId":"m-001", "majorCourse": [ { "courseName":"C++" ...