Rspec中expect_to_receive未识别方法调用问题排查
测试方法调用验证失败的原因与解决方案
核心问题
测试中设置调用期望的对象实例,和实际代码执行时调用的不是同一个实例。
原因分析
你的测试代码执行expect(Payments.paymentProviderFactory.provider).to receive(:debit).once时,Payments.paymentProviderFactory.provider返回了一个实例A;当subject.call执行时,Payments.paymentProviderFactory.provider又生成并返回了一个新的实例B。你给实例A设置了调用期望,但实际执行debit的是实例B,所以测试框架统计到实例A的debit调用次数为0。
解决方案
1. 确保Provider是单例实例
如果业务上paymentProviderFactory.provider应该返回同一个实例,修改Factory的provider方法,加入实例缓存:
class Payments::PaymentProviderFactory def provider # 第一次调用创建实例,后续调用返回缓存的实例 @provider ||= Payments::CardPaymentProvider.new end end
2. 测试中存根Provider实例
在测试里提前创建一个固定实例,让Factory的provider方法始终返回这个实例,再对它设置期望:
let(:payment_provider) { Payments::CardPaymentProvider.new } before do # 存根Factory,让它每次都返回同一个实例 allow(Payments.paymentProviderFactory).to receive(:provider).and_return(payment_provider) end it "triggers the debit method" do expect(payment_provider).to receive(:debit).once subject.call end
3. 验证任意实例的方法调用(不推荐)
如果不需要关注具体实例,只是想确认debit方法被执行过,可以用expect_any_instance_of:
it "calls debit on any CardPaymentProvider instance" do expect_any_instance_of(Payments::CardPaymentProvider).to receive(:debit).once subject.call end
注意:这种方式不推荐,因为它会匹配该类的所有实例,可能掩盖代码中的实例创建逻辑问题。
为什么断点能看到方法被调用?
因为实际确实有CardPaymentProvider实例执行了debit方法,但这个实例和你测试中设置期望的实例不是同一个,所以测试框架没有统计到这次调用。
内容的提问来源于stack exchange,提问作者Syl
相关产品推荐
相关产品推荐

