如何在Jest中测试TypeScript类构造函数的参数数量与类型?
测试TypeScript类构造函数的参数数量与类型
假设我在MyClass.ts中定义了这样一个简单类:
export class MyClass { private foo:string; private bar:number; constructor(foo:string, bar:number){ this.foo = foo; this.bar = bar; } }
我需要编写测试用例,检查MyClass构造函数的参数数量是否正确,理想情况下还能校验参数类型与顺序。也就是说,当MyClass被修改成以下任意一种情况时,测试要失败:
- 情况1:参数数量不足
export class MyClass { constructor(foo:string){} }
- 情况2:参数数量过多
export class MyClass { constructor(foo:string, bar:number, a:string){} }
- 情况3:参数顺序颠倒
export class MyClass { constructor(bar:number, foo:string){} }
- 情况4:参数类型任意化
export class MyClass { constructor(a:any, b:any){} }
解决方案
1. 检查构造函数参数数量
JavaScript/TypeScript中,函数的length属性会返回其声明的参数个数,直接用这个特性就能快速校验参数数量:
import { MyClass } from './MyClass'; test('MyClass构造函数参数数量应为2个', () => { expect(MyClass.length).toBe(2); });
这个测试可以直接拦截参数数量过多或过少的情况(比如上面的情况1、情况2)。
2. 校验参数类型与顺序
TypeScript编译后会擦除类型信息,所以需要通过运行时验证或元数据来实现类型与顺序的校验:
方法一:通过实例属性反向验证
传入特定类型的参数,检查实例的私有属性是否正确接收了对应值,以此间接验证参数的类型和顺序:
import { MyClass } from './MyClass'; test('MyClass构造函数参数类型与顺序正确', () => { const testFoo = '测试字符串'; const testBar = 12345; const instance = new MyClass(testFoo, testBar); // 由于foo和bar是私有属性,通过类型断言绕过TypeScript的访问限制 expect((instance as any).foo).toBe(testFoo); expect((instance as any).bar).toBe(testBar); });
这个测试能覆盖所有异常情况:参数顺序颠倒时,属性值会和预期不符;参数类型任意化且未正确赋值时,属性会是undefined或错误类型的值。
方法二:使用反射元数据直接校验类型
借助reflect-metadata库保留TypeScript的类型元数据,实现更直接的类型校验:
- 安装依赖:
npm install reflect-metadata --save-dev
- 修改
tsconfig.json,启用元数据相关配置:
{ "compilerOptions": { "emitDecoratorMetadata": true, "experimentalDecorators": true, // 其他已有配置... } }
- 给
MyClass添加装饰器(用于触发元数据生成):
import 'reflect-metadata'; // 装饰器无需额外逻辑,仅用于让TypeScript生成参数类型元数据 @Reflect.metadata('design:paramtypes', [String, Number]) export class MyClass { private foo:string; private bar:number; constructor(foo:string, bar:number){ this.foo = foo; this.bar = bar; } }
- 编写测试用例:
import 'reflect-metadata'; import { MyClass } from './MyClass'; test('MyClass构造函数参数类型与顺序符合预期', () => { const paramTypes = Reflect.getMetadata('design:paramtypes', MyClass); expect(paramTypes).toEqual([String, Number]); });
这个测试会直接获取构造函数的参数类型元数据,一旦参数类型、顺序发生变化,测试就会失败。
内容的提问来源于stack exchange,提问作者scibuff
相关产品推荐
相关产品推荐

