I encountered challenges while testing a JavaScript file with Jest that involves multiple interactions with ThreeJS. Initially, I attempted to test without mocking ThreeJS, but it resulted in errors:
● TestSuite › Should instantiate a renderer attached to a specific element of the DOM
TypeError: Cannot read property 'getExtension' of null
36 | */
37 | constructor(containerId: string) {
> 38 | this.renderer = new WebGLRenderer({ antialias: true });
39 | this.attachRenderer(containerId);
40 | this.createCamera();
41 | this.createScene();
This issue arose due to the fact that we were testing in an environment resembling a browser without a webgl context. To address this, I decided to mock ThreeJS.
Subsequently, I mocked my external module using jest.mock("three");
● TestSuite › Should instantiate a renderer attached to a specific element of the DOM
TypeError: this.renderer.setSize is not a function
64 | throw new Error("Cannot find DOM element object matching the specified ID: " + containerId);
65 | }
> 66 | this.renderer.setSize(window.innerWidth, window.innerHeight);
67 | element.appendChild(this.renderer.domElement);
68 | }
69 |
As expected, this occurred because every jest mock returns undefined
, so new WebGLRenderer();
also returns undefined
which is not usable.
Currently, my workaround involves defining all ThreeJS components in my test file:
jest.mock("three", () => ({
Scene: class Scene {
public add(): void {
return;
}
},
WebGLRenderer: class WebGlRenderer {
public render(): void {
return;
}
public setSize(): void {
return;
}
}
// And a lot more...
}));
However, I understand that this is not the most efficient solution. Previously, I followed a similar approach by creating a file in mocks/three.js (https://jestjs.io/docs/en/manual-mocks), which worked fine but did not fulfill my requirements.
Is there a more effective way to test this file without having to manually mock ThreeJS components extensively?