The issue arises when Jest fails to align with a custom error type while utilizing dynamic imports

In my project, I have defined a custom error in a file named 'errors.ts':

export class CustomError extends Error {
    constructor(message?: string) {
        super(message);
        Object.setPrototypeOf(this, Error.prototype);
        this.name = this.constructor.name;
    }
}

Additionally, there is a module that utilizes this custom error in a file called 'main.ts':

import { CustomError } from './errors';

let called = false;
export default {
    throwAfterFirst: (): void => {
        if (called) throw new CustomError();
        called = true;
    },
};

To test this setup with jest and utilize dynamic imports to reset a variable, I created the following test file:

import { CustomError } from './errors';

let main: typeof import('./main').default;
const load = async (): Promise<typeof import('./main').default> => {
    jest.resetModules();
    main = (await import('./main')).default;
};

describe('Main', () => {
    beforeEach(async () => {
        await load();
    });

    it('should throw on second time', () => {
        main.throwAfterFirst();
        expect(() => main.throwAfterFirst()).toThrowError(CustomError);
    });

    it('should still throw on second time', () => {
        main.throwAfterFirst();
        expect(() => main.throwAfterFirst()).toThrowError(CustomError);
    });
});

However, there seems to be an issue where the toThrowError function is not correctly matching the expected and received constructors for the CustomError. This problem does not occur when using regular errors like TypeError. Interestingly, without dynamic importing, the tests pass successfully as shown below:

import { CustomError } from './errors';
import main from './main';

describe('Main', () => {
    it('should throw on second time', () => {
        main.throwAfterFirst();
        expect(() => main.throwAfterFirst()).toThrowError(CustomError);
    });
});

It appears that due to the dynamic import usage, the CustomError may not be recognized correctly or have the same prototype causing the mismatch. What am I overlooking here, and what steps can I take to fix this testing issue? I still aim to specifically check for the CustomError and avoid using toThrow which matches any error. It's worth noting that toThrow works in this scenario.

Answer №1

Here is the workaround I discovered:

let main: typeof import('./main').default;
let Errors: typeof import('./errors');
const load = async (): Promise<void> => {
    jest.resetModules();
    main = (await import('./main')).default;
    Errors = await import('./errors');
};

describe('Main', () => {
    beforeEach(async () => {
        await load();
    });

    it('should throw on second time', () => {
        manager.throwAfterFirst();
        expect(() => manager.throwAfterFirst()).toThrowError(Errors.CustomError);
    });

    it('should still throw on second time', () => {
        manager.throwAfterFirst();
        expect(() => manager.throwAfterFirst()).toThrowError(Errors.CustomError);
    });
});

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

Displaying properties of a class in Typescript using a default getter: Simplified guide

Here is an interface and a class that I am working with: export interface ISample { propA: string; propB: string; } export class Sample { private props = {} as ISample; public get propA(): string { return this.props.propA; } public se ...

Having trouble getting material-ui container to work with custom breakpoints in TypeScript?

Currently, I am exploring material-ui and typescript within my educational project. However, I have encountered a perplexing issue for which I am seeking assistance. In this project, I utilize custom breakpoints in the material-ui theme settings. import { ...

Angularjs 2 Error: Unable to access the 'infos' property of an undefined object using the Http Client

I've been working on an AngularJS app for about a week now, developing a backoffice application for my service. My main challenge lies in using data retrieved from a remote server. I have 4 HTTP GET requests in my app - 2 of them fetching lists of us ...

Exploring the TypeScript Type System: Challenges with Arrays Generated and Constant Assertions

I am currently grappling with a core comprehension issue regarding TypeScript, which is highlighted in the code snippet below. I am seeking clarification on why a generated array does not function as expected and if there is a potential solution to this pr ...

What is the best way to showcase a variable from a typescript file in an HTML file with Angular?

In my TypeScript file, I have the following function: ngOnInit() { if (sessionStorage['loyalPage']) { this.page = Number(sessionStorage['loyalPage']); } this.webService.getLoyalPlayers(this.pag ...

Utilizing Azure Function Model v4: Establishing a Connection with Express.js

Using Model v4 in my Azure function index.ts import { app } from "@azure/functions"; import azureFunctionHandler from "azure-aws-serverless-express"; import expressApp from "../../app"; app.http("httpTrigger1", { methods: ["GET"], route: "api/{*segme ...

Encountering the error message "SyntaxError: Cannot use import statement outside a module" is often linked with the mui-color-input component and Create React App

After integrating the mui-color-input library into my create-react-app project, I encountered a problem with the component test despite the project building successfully. ● Test suite failed to run Jest encountered an unexpected token Jest fai ...

After I deploy my Next.js code to Vercel, including Google Analytics added by @next/third-parties, I am encountering an error that does not appear in development mode

Lately, I completed a next.js project and integrated Google Analytics using @next/third-parties/google. During development, everything worked perfectly, but upon deploying it to vercel.com, an error popped up. ` ./app/layout.tsx:3 ...

Defining Multiple Types in Typescript

I have created an interface in a TypeScript definition file named d.ts: declare module myModule { interface IQedModel { field: string | string[]; operator: string; } } In an Angular controller, I have utilized this interface like ...

Creating custom components that encapsulate the functionality of Angular Material tabs component

I am aiming to incorporate the Angular Material tabs component within my shared components. Here is the component I'm attempting to wrap: Note: Each tab can display a component: <mat-tab-group> <mat-tab label="First"> Content ...

Click on the button to generate a PDF report using Internet Explorer 11

After encountering some challenges with printing a PDF report specifically on IE 11, I am reaching out for help. The code snippet below works perfectly in Chrome, but when it comes to IE 11, everything falls apart. Just to provide some context, I am develo ...

Unexpected Issue: Angular 12 Encounters JIT Compiler Unavailability

Lately, I've been encountering a persistent issue with an error message: Uncaught Error: JIT compiler unavailable. Ever since I upgraded from Angular version 8 to 12, whenever I run the ng build --prod --output-path = dist command and build Angular, e ...

Problem with timing in token interceptor and authentication guard due to injected service

Currently, I am facing an issue where I need to retrieve URLs for the auth service hosted on AWS by reading a config.json file. In order to accomplish this, I created a config service that reads the config file and added it as a provider in app.module. Eve ...

Exported data in Vue3 components cannot be accessed inside the component itself

Essentially, I'm working on creating a dynamic array in Vue3. Each time a button is clicked, the length of the array should increase. Below is the code snippet. <div class="package-item" v-for="n in arraySize"></div> e ...

Eliminate a specific choice from a drop-down menu in an Angular application

I am implementing a feature where clicking on a button adds more select drop downs. I want to ensure that the selected options in these new dropdowns do not duplicate any already chosen options. Below is the code snippet used for the select drop down: < ...

Is there a way to access a function or variable from within the scope of $(document)?

Whenever I attempt to utilize this.calculatePrice, it does not work and I am unable to access the external variable minTraveller from within the function. numberSpin(min: number, max: number) { $(document).on('click', '.number-spinner b ...

Issues arise when attempting to override attributes within the HTML of a parent component in Angular

Why does overriding an attribute in a child class that extends from another not work as expected? Here's a made-up scenario to simplify the issue: Parent class file: gridbase.component.ts import { Component, OnInit } from '@angular/core'; ...

Tips for toggling visibility in Angular 2

I utilized [hidden] in the following way where the value of "secondTab" is set to true. <form #siteForm="ngForm" novalidate (ngSubmit)="saveSite(siteForm.value,siteForm.valid)" class="admin-modal"> <div class="txt-danger">{{errorMessage}}&l ...

Is there a way to reset the yAxes count of a chart.js chart in Angular when changing tabs?

I am currently using chart.js within an Angular framework to visually display data. Is there any method available to reset the y-axis data when changing tabs? Take a look at this Stackblitz demo for reference. Upon initial loading of the page, the data ...

Testing the mirkoORM entities at a unit level

Trying to perform a unit test on a method within a MikroORM entity, I am attempting to populate a mikroORM collection field with test data. Specifically, I am using jest for this task: describe('Team Tests', () => { it('isLeader shoul ...