如何在Node.js中使用Jest模拟类的只读属性CHUNK_SIZE
解决Jest测试中修改只读/私有属性的问题
你遇到的问题核心在于:jest.spyOn() 无法直接修改只读属性或私有属性——前者因为没有可写的setter,后者如果是ES私有字段或TypeScript编译后的私有属性,spyOn无法直接访问到。以下是具体的解决方案:
一、修改只读属性 CHUNK_SIZE
如果 CHUNK_SIZE 是类的实例只读属性(比如通过 readonly 关键字定义,或用 Object.defineProperty 设为只读),spyOn() 无法替换它,因为它没有可写的setter。此时需要用 Object.defineProperty 重新定义该属性的取值:
示例测试用例
test('post 返回 true 当 CHUNK_SIZE 被设为1', () => { const controller = new SearchController(); // 强制修改只读属性的值 Object.defineProperty(controller, 'CHUNK_SIZE', { value: 1, writable: true // 可选,后续若需再次修改可添加 }); const result = controller.post('test-data'); expect(result).toBe(true); });
如果 CHUNK_SIZE 是静态只读属性,则需要修改类本身的属性:
test('修改静态只读CHUNK_SIZE', () => { Object.defineProperty(SearchController, 'CHUNK_SIZE', { value: 1 }); const controller = new SearchController(); expect(controller.post('test')).toBe(true); });
二、修改私有属性 chunk 的长度
根据你使用的是TypeScript私有属性还是ES原生私有字段,处理方式不同:
1. TypeScript的private属性(编译后为普通属性)
TypeScript的private关键字编译后,属性会被转化为带下划线的普通属性(比如_chunk),可以直接访问并修改:
test('通过修改chunk长度让post返回true', () => { const controller = new SearchController(); // 直接修改编译后的私有属性 controller._chunk = new Array(99); // 初始长度99,push后变为100,等于默认CHUNK_SIZE const result = controller.post('test'); expect(result).toBe(true); });
2. ES原生私有字段(#chunk)
如果是用ES6+的私有字段语法(#chunk),需要通过Object.getOwnPropertySymbols获取私有字段的符号后修改:
test('修改ES私有字段#chunk的长度', () => { const controller = new SearchController(); // 找到#chunk对应的符号 const chunkSymbol = Object.getOwnPropertySymbols(controller).find( sym => sym.description === '#chunk' ); // 修改私有字段的值 controller[chunkSymbol] = new Array(99); const result = controller.post('test'); expect(result).toBe(true); });
为什么jest.spyOn()没用?
jest.spyOn() 的核心作用是替换对象的可写属性或方法:
- 对于只读属性,由于没有setter,spyOn无法覆盖其取值;
- 对于私有属性,ES原生私有字段对外不可见,TypeScript的私有属性编译后虽然是普通属性,但spyOn默认不会访问这类约定俗成的"私有"属性;
- spyOn更适合用来mock方法的实现,而非修改属性的静态值。
内容的提问来源于stack exchange,提问作者CEJ
相关产品推荐
相关产品推荐

