Allow using `vi.mock` (and related) functions in tests
已经有一个关联 PR 被合并了。
- #32655 来自 @clydin —— 已合并
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 20/100
- Issue 类型
- 功能
- 描述清晰度
- 需要澄清
- 活跃度
- 停滞
- 技术栈
- angular, typescript, vite
调研方向
从新的 Angular 单元测试构建器及其 Vite 打包路径开始,然后跟踪 vi.mock 调用在哪些位置被拒绝,以及 spec 文件和 setupFiles 如何被转换。审查关于编译时检测、提升、导入重写和 mock 注册表的拟议要求。完成意味着支持列出的 vi 函数,同时保留 ESM 实时绑定、sourcemaps、coverage,并且不使用运行时模块加载器。
由索引模型根据 Issue 内容生成。
描述
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.
- 主要语言
- TypeScript
- 星标
- 27k
- 派生
- 11.8k
- 平均合并
- 16 小时 21 分钟
- 30 天内合并 PR
- 170
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
angular/angular-cli 的其他 Issue
-
area: @angular/build gemini-triaged
难度 2/5 1-3 小时 新手友好度 74/100
angular/angular-cli#33955 ·
-
area: @angular/cli gemini-triaged
难度 2/5 1-3 小时 新手友好度 72/100
angular/angular-cli#33055 · 1 条评论 · 3 个 reaction ·
-
angular/build:library area: @angular/build gemini-triaged
angular/angular-cli#34131 · 已指派 1 人 ·
-
angular/build:library area: @angular/build gemini-triaged
angular/angular-cli#34130 · 已指派 1 人 ·
-
angular/build:library area: @angular/build gemini-triaged
angular/angular-cli#34128 · 已指派 1 人 ·
查看 angular/angular-cli 的全部 Issue
相似的 Issue
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
难度 1/5 1 小时以内 新手友好度 95/100
-
Ecosystem: ClawMetry — the Qwen Code reader is now free and open source (follow-up to #9294 / #9338) 未关闭category/integration priority/P3 scope/documentation status/ready-for-human type/feature-request
难度 1/5 1 小时以内 新手友好度 84/100
-
area:auth FE mvp P3
难度 2/5 1-3 小时 新手友好度 88/100
klasolsson81/jobbliggaren#1788 ·
-
难度 2/5 1-3 小时 新手友好度 74/100
get-convex/migrations#69 ·
-
accessibility angular bug good first issue typescript ux
难度 2/5 1-3 小时 新手友好度 88/100
apache/fineract-backoffice-ui#584 · 1 条评论 ·