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.