I am using typescript and jest. I'm trying to perform a very simple unit test but it always fails. Here is my code:
// init.ts
let initialized = false;
let secretName: string;
export function init(name: string) {
if (initialized) {
throw new Error("Cannot re-initialize.");
}
secretName = name;
initialized = true;
}
export function getSecret(): string {
return secretName;
}
// init.test.ts
describe("init", () => {
async function getTestSubject() {
return await import("./init");
}
it("should set the secret name properly", async () => {
const init = await getTestSubject();
init.init("bruce wayne");
expect(init.getSecret()).toEqual("bruce wayne");
});
it("should throw an exception if initialized more than once", async () => {
const init = await getTestSubject();
const callInit = function() {
init.init("bruce wayne");
};
callInit();
expect(callInit).toThrowError("Cannot re-initialize.");
});
});
The second unit tests fails due to an exception being thrown. When the first "callInit()" is called that should be the first time that init is called for that unit test. However, it is the second time that it is called when considering both unit tests.
I thought by dynamically importing the test subject (e.g. "./init") within each test, I would avoid this problem as I originally tried importing init at the top like this:
import {init, getSecret} from "./init";
Any ideas on how to test this? I think this is a pretty basic test case so either there is a huge limitation in jest or I'm just missing something obvious...
Thanks!
I was able to get this to work by calling jest.resetModules() in a beforeEach() in order to reset the module namespaces before each test.
let initModule
beforeEach(() => {
jest.resetModules()
initModule = require('./init')
})
it('should set the secret name properly', () => {
initModule.init('bruce wayne')
expect(initModule.getSecret()).toEqual('bruce wayne')
})
it('should throw an exception if initialized more than once', () => {
const callInit = () => initModule.init('bruce wayne')
callInit()
expect(callInit).toThrowError('Cannot re-initialize.')
})
You're correct that it's necessary here to import the other module inline, because it's not possible to accomplish this reset of the module namespace using the standard ES6 import. In the example above though, I used what I think is the simpler require() approach to do so.
If you're using typescript and still wish to strongly type initModule, you can still import it using the standard ES6 import in order to fetch the type.
import * as InitModule from './init'
let initModule: typeof InitModule
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With