如何使用Jest模拟TypeScript类的Getter属性?
问题:Jest自动模拟TypeScript类的公共Getter属性失败
待测试代码
MyClass.ts
import Dependency from "./Dependency"; export default class MyClass { public constructor(private dependency: Dependency) {} public DoIt(): string { return this.dependency.MyProp; } }
Dependency.ts
export default class Dependency { public get MyProp(): string { return "A string"; } }
现有测试代码(存在问题)
import MyClass from "./MyClass"; import Dependency from "./Dependency"; jest.mock("./Dependency"); // 使用自动模拟 it("测试DoIt方法返回模拟的MyProp值", () => { // 准备 const dependency = new Dependency(); const sut = new MyClass(dependency); // dependency.MyProp = "Another string"; // 错误:无法分配给只读属性“MyProp” jest.spyOn(dependency, "MyProp", "get").mockReturnValueOnce("Another string"); // 错误:MyProp属性不存在 // 执行 const retval = sut.DoIt(); // 断言 expect(retval).toStrictEqual("Another string"); });
问题说明:Jest自动模拟默认只会识别类的方法,不会处理getter属性,导致运行时MyProp值为undefined,既无法直接赋值修改,用jest.spyOn也会提示属性不存在。需要在保留自动模拟的前提下,正确模拟该公共getter属性。
解决方案
方法1:补充自动模拟的getter定义
在项目中创建__mocks__/Dependency.ts文件(Jest会自动识别该目录下的模拟文件,无需修改原测试的jest.mock调用):
const mockMyProp = jest.fn(() => "A string"); export default class Dependency { public get MyProp(): string { return mockMyProp(); } } // 暴露mock函数,方便测试中修改返回值 export { mockMyProp };
然后修改测试代码:
import MyClass from "./MyClass"; import Dependency, { mockMyProp } from "./Dependency"; jest.mock("./Dependency"); it("测试DoIt方法返回模拟的MyProp值", () => { // 准备 mockMyProp.mockReturnValueOnce("Another string"); const dependency = new Dependency(); const sut = new MyClass(dependency); // 执行 const retval = sut.DoIt(); // 断言 expect(retval).toStrictEqual("Another string"); expect(mockMyProp).toHaveBeenCalled(); });
方法2:用Object.defineProperty重写实例getter
无需额外创建mock文件,直接在测试中修改实例的getter:
import MyClass from "./MyClass"; import Dependency from "./Dependency"; jest.mock("./Dependency"); it("测试DoIt方法返回模拟的MyProp值", () => { // 准备 const dependency = new Dependency(); // 重写getter并设置可配置,允许后续修改 Object.defineProperty(dependency, "MyProp", { get: jest.fn().mockReturnValue("Another string"), configurable: true }); const sut = new MyClass(dependency); // 执行 const retval = sut.DoIt(); // 断言 expect(retval).toStrictEqual("Another string"); });
方法3:类型断言配合jest.spyOn
通过类型断言告诉TypeScript自动模拟后的实例包含该getter属性,再使用jest.spyOn:
import MyClass from "./MyClass"; import Dependency from "./Dependency"; jest.mock("./Dependency"); it("测试DoIt方法返回模拟的MyProp值", () => { // 准备 const dependency = new Dependency() as unknown as { MyProp: string }; jest.spyOn(dependency, "MyProp", "get").mockReturnValue("Another string"); const sut = new MyClass(dependency as Dependency); // 执行 const retval = sut.DoIt(); // 断言 expect(retval).toStrictEqual("Another string"); });
内容的提问来源于stack exchange,提问作者Jupiter
相关产品推荐
相关产品推荐

