TypeScript测试自动化中如何自动向类构造函数注入Page实例?
TypeScript 编译期安全的Page依赖注入实现方案
核心思路
通过定义约束构造函数类型的泛型Provider,自动注入固定的Page实例作为构造函数第一个参数,同时保留剩余参数的类型校验,所有逻辑在编译期完成类型推导,无运行时类型损耗。
实现步骤
1. 基础类型定义
首先定义统一的构造函数约束,所有需要注入Page的类都符合该类型规范:
// 替换为你实际的Page类型定义(如Playwright/Puppeteer的Page类型) interface Page {} interface NavigationStrategy {} // 约束:构造函数第一个参数为Page,后续为自定义参数,返回类实例T type PageDependentCtor<T, Args extends any[]> = new (page: Page, ...args: Args) => T;
2. PageProvider实现
提供带重载的create方法,根据构造函数的参数个数自动返回对应结果:
- 若构造函数除Page外无其他参数,直接返回实例
- 若有其他参数,返回接收剩余参数的函数,参数类型完全继承构造函数定义
class PageProvider { constructor(private page: Page) {} // 重载1:无额外参数的类,直接返回实例 create<T>(ctor: PageDependentCtor<T, []>): T; // 重载2:有额外参数的类,返回接收剩余参数的函数 create<T, Args extends any[]>(ctor: PageDependentCtor<T, Args>): (...args: Args) => T; // 方法实现 create<T, Args extends any[]>(ctor: PageDependentCtor<T, Args>) { // 构造函数length属性为形参个数,减1即为除Page外需要的参数个数 if (ctor.length === 1) { return new ctor(this.page); } return (...args: Args) => new ctor(this.page, ...args); } }
3. 业务类示例(现有代码不需要修改)
class LHSNavigation implements NavigationStrategy { constructor(page: Page) {} } class SearchPage { constructor(page: Page) {} } class Account { constructor(page: Page, accountNumber: string) {} } class Navigation { constructor(page: Page, navigation: NavigationStrategy) {} }
使用示例
完全符合期望的调用方式,且所有参数错误都会在编译期抛出:
it("some test", async () => { const page = await browser.newPage(); const pageProvider = new PageProvider(page); // 无额外参数直接获取实例 const searchPage = pageProvider.create(SearchPage); // 有额外参数调用返回函数传参,参数类型自动校验 const account = pageProvider.create(Account)("2135"); // 嵌套依赖也可直接通过同一provider创建 const navigation = pageProvider.create(Navigation)( pageProvider.create(LHSNavigation)() ); })
可选优化
如果希望支持pageProvider.create(Navigation, LHSNavigation)这类传参自动实例化依赖的写法,只需要给create方法增加对应重载,在实现中判断传入的第二个参数是否为Page依赖类,自动调用create实例化即可,类型推导逻辑可以复用现有实现。
内容的提问来源于stack exchange,提问作者AlexK
相关产品推荐
相关产品推荐

