Jest:如何Mock ES6类中的单个成员函数
测试ES6类内部方法调用的几种实用方案
这个问题我之前也碰到过,其实测试类内部方法的调用并不难,核心思路就是借助测试框架的**间谍(Spy)**功能,来监视目标方法的调用情况。下面给你几种不同测试框架下的实现方案:
方案一:使用Jest(最常用)
如果你用Jest作为测试框架,直接用jest.spyOn()就能轻松实现。因为ES6类的方法默认挂载在原型上,所以我们可以直接监视原型上的bar方法:
import MyClass from './MyClass'; test('foo方法应该调用bar方法', () => { // 1. 监视MyClass原型上的bar方法,创建一个间谍 const barSpy = jest.spyOn(MyClass.prototype, 'bar'); // 2. 生成类的实例 const myInstance = new MyClass(); // 3. 调用待测试的foo方法 myInstance.foo(); // 4. 验证bar方法是否被调用(还可以用toHaveBeenCalledTimes(n)验证调用次数) expect(barSpy).toHaveBeenCalled(); // 5. 测试结束后恢复原方法,避免影响其他测试用例 barSpy.mockRestore(); });
如果你的bar方法是在构造函数里重新赋值给实例的(比如this.bar = () => {...}),那就要改成监视实例上的方法:
const myInstance = new MyClass(); const barSpy = jest.spyOn(myInstance, 'bar');
方案二:使用Sinon + Mocha/Chai
要是你用的是Mocha搭配Sinon的组合,思路和Jest一致,利用Sinon的spy功能来监视方法:
import { expect } from 'chai'; import sinon from 'sinon'; import MyClass from './MyClass'; describe('MyClass', () => { it('foo方法应该调用bar方法', () => { // 创建间谍并挂载到类的原型上 const barSpy = sinon.spy(MyClass.prototype, 'bar'); const myInstance = new MyClass(); myInstance.foo(); // 验证bar是否被调用过一次 expect(barSpy.calledOnce).to.be.true; // 恢复原方法 barSpy.restore(); }); });
方案三:手动重写实例方法(无需额外工具)
如果不想用测试框架的spy功能,也可以手动重写实例的bar方法,通过标记来判断是否被调用:
import MyClass from './MyClass'; test('foo方法调用了bar方法', () => { let barIsCalled = false; const myInstance = new MyClass(); // 重写bar方法,调用时标记状态 myInstance.bar = () => { barIsCalled = true; // 如果需要保留原方法的逻辑,可以加上: // MyClass.prototype.bar.call(this); }; myInstance.foo(); // 验证标记是否为true expect(barIsCalled).toBe(true); });
注意事项
如果你的bar是私有方法(用ES6私有字段#bar定义的),那上面的方法都无法生效,因为私有方法无法从类外部访问。这种情况下,建议要么测试bar方法带来的业务副作用,要么考虑把bar的逻辑抽成独立的模块(比如单独的工具函数),这样就能像外部依赖一样Mock了。
内容的提问来源于stack exchange,提问作者Bauza23
相关产品推荐
相关产品推荐

