Allow using `vi.mock` (and related) functions in tests
Una pull request collegata è già stata integrata.
- #32655 di @clydin — integrata
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 20/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Da chiarire
- Stato di attività
- Ferma
- Stack tecnologico
- angular, typescript, vite
- Ambito
- build-system, testing-qa
Direzione di ricerca
Inizia con il nuovo builder di unit test Angular e il relativo percorso di bundling di Vite, quindi traccia dove vengono rifiutate le chiamate a vi.mock e come vengono trasformati i file spec e setupFiles. Esamina i requisiti proposti per il rilevamento in fase di compilazione, l’hoisting, la riscrittura degli import e il registro dei mock. Il lavoro è completato quando sono supportate le funzioni vi elencate, preservando al contempo i live binding ESM, le sourcemap, la coverage e senza un module loader a runtime.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Which @angular/* package(s) are relevant/related to the feature request?
core
Description
With the new Angular unit-test builder (Vite), test files are bundled into unified chunks.
Because of this full bundling step:
- ESM modules are statically linked at build time
- There is no runtime module graph available
- vi.mock() cannot intercept module loading
- Mocking entire modules (components/services/modules) is not possible
Currently if we use vi.mock function for automocking component/directives/services/pipes/etc..., we got an error:
Error: The "vi.mock" and related methods are not supported with the Angular unit-test system. Please use Angular TestBed for mocking.
TestBed overrides are insufficient because:
- They replace Angular metadata (providers/imports), not module implementation
- They cannot replace pure TS logic or side effects
- They do not intercept ESM import bindings
Proposed solution
Instead of runtime interception (like Vitest normally does), Angular test builder should:
- Detect
vi.mock()calls at compile time (in spec files, and in setupFiles) - Hoist them
- Rewrite import bindings to use a generated mock registry
- Replace module resolution during bundling
I suggest to create esbuild plugin, that:
- Parse test file AST
- Detect:
vi.mock()vi.unmock()vi.doMock()vi.doUnmock()vi.importMock()vi.importActual()vi.hoisted()
- Hoist mock calls
- Rewrite imports
Example Transform Injectable
Before:
import { MyService } from './my-service';
import { MyOtherService } from './my-other-service';
vi.mock('./my-service', () => ({
MyService:
@Injectable({providedIn: 'root'})
class {
get() { return 'mock'; }
}
}));
vi.mock('./my-other-service');
test(() => {
const myService = new MyService();
const myOtherService = new MyOtherService();
});
After:
// should initialize once in one environment
const __angularViMocks = (globalThis.__angular_vi_mocks ??= new Map<string, any>());
__angularViMocks.set(
'./my-service',
(() => ({
MyService: class {
get() { return 'mock'; }
static ɵprov = {
providedIn: 'root',
factory: () => new this();
};
static ɵfac = () => new this();
}
}))()
);
__angularViMocks.set(
'./my-other-service',
(() => ({
MyOtherService: class {
get = vi.fn(); // maybe better to put `vi.fn()` to MyOtherService.prototype.get = vi.fn();
static ɵprov = {
providedIn: 'root',
factory: () => new this();
};
static ɵfac = () => new this();
}
}))()
);
import * as __angularViActualMod1 from './my-service';
import * as __angularViActualMod2 from './my-other-service';
// We should replace that import in every dependent chunk.
const { MyService } = __angularViMocks.get('./my-service') ?? __angularViActualMod1;
const { MyOtherService } = __angularViMocks.get('./my-other-service') ?? __angularViActualMod2;
Requirements:
- Must mock full implementation (not only metadata) for any modules, as
vi.mock()does - Must stub components, services, modules, pipes, directives both metadata and implementation
- Must preserve ESM live bindings semantics
- Must preserve sourcemaps and coverage
- Must not require runtime module loader
Alternatives considered
Currently we have no choice, but stay with slow and inefficient jest + jest-preset-angular.
I've implemented deep-automocking infrastructure for jest.mock() ng-automocks-jest, it can stub any angular entities, both metadata and implementation.
- Lingua principale
- TypeScript
- Stelle
- 27k
- Fork
- 11.8k
- Merge medio
- 16h 21m
- PR unite (30g)
- 170
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di angular/angular-cli
-
area: @angular/build gemini-triaged
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
angular/angular-cli#34129 ·
-
area: @angular/cli gemini-triaged
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
angular/angular-cli#34057 ·
-
area: @angular/build gemini-triaged
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
angular/angular-cli#33955 ·
-
area: @angular/cli gemini-triaged
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
angular/angular-cli#33055 · 1 commento · 3 reazioni ·
-
angular/build:library area: @angular/build gemini-triaged
angular/angular-cli#34131 · 1 assegnatario ·