New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Jest/ESBuild mocking JS modules #25582
Comments
Note: There is a related discussion at angular/angular#50756. |
I believe this one is not quite related. It's about how Zones are configured. But here the problem is global. It's about literally every package that you import. Even if you import a function that you have created in a separate file. You still cannot mock it. |
@gultyayev - have you tried using jest's Module Mocking in ESM for this use case?
|
jest.mock('foo');
import { bar } from 'foo'; // Hoisted, happens before `jest.mock`. There are two ways I'm aware of to get this mock to work. The first is to use CommonJS, which does not hoist jest.mock('foo');
const { bar } = require('foo'); // No hoisting. It sounds like we could fix this by converting authored ESM code into CommonJS tests, however even that doesn't work. ESM format requires this hoisting, so a correct transformation of ESM into CommonJS would also necessitate hoisting the The second approach is to use a dynamic import, which also isn't subject to hoisting: jest.mock('foo');
const { bar } = await import('foo'); // Also no hoisting. Jest does have a built-in transform which automatically hoists jest.mock('foo');
// Transformed from:
// import { bar } from 'foo';
// import { Component } from '@angular/core';
const [ { bar }, { Component } ] = await Promise.all([
import('foo'),
import('@angular/core'),
]); Those are pretty invasive changes and I'm not totally convinced they're the right path forward here. The Jest team is evaluating this approach but hasn't done it yet and doesn't seem to consider Even if those timing issues were fixed, we're currently exploring pre-bundling Jest tests, meaning the import of The ideal solution is probably to use Angular's dependency injection to stub out any dependencies you need to mock, though I get that can be a big mental shift for a lot of developers used to using these tools outside of Angular. For now I'm inclined to follow Jest's lead and leave This will likely be confusing for users to have jest.mock = () => {
throw new Error('jest.mock is unsupported, see: https://github.com/angular/angular-cli/issues/25582');
}; However that would break for legitimate dynamic import use cases which could otherwise work, so I'm not convinced that's the best solution either. I expect this will be a common challenge for Jest users, so I'll leave this issue open just to collect feedback about this particular rough edge. I suspect the best thing we can do for now though is hope the Jest team is able to come up with a more elegant solution for ESM module mocking which we can better apply to Angular. |
Command
test
Is this a regression?
The previous version in which this bug was not present was
No response
Description
With Jest Angular started to use ES Build internally. This causes ES Modules in the output with non-configurable methods/properties. As a result, we cannot mock JS modules. This leads to tests that pull lots of external dependencies (utility functions, config objects etc.) that are not provided using the DI and hence cannot be stubbed using Angular DI.
Minimal Reproduction
Scaffold an app and use Jest as a testing tool. Modify AppComponent.ngOnInit
In the test try to stub the
isDevMode
.Exception or Error
Anything else relevant?
This feels like a big deal, because most of the current state tests will become invalid. Furthermore, current behavior makes unit tests more of the integration sorts.
The text was updated successfully, but these errors were encountered: