如何用RSpec统计递归调用自身的Worker的执行次数?
测试Myworker递归调用次数的正确方案
问题根源
你之前的错误在于完全Stub掉了perform_async的原逻辑——只做了计数,但没有让Worker实际执行递归调用,所以只会统计到第一次触发,后续递归根本没跑起来。
解决思路
要在保留perform_async原执行逻辑的前提下,统计它的调用次数。这样递归能正常触发,次数统计也准确。
具体实现
1. 准备测试数据
先创建足够多的关联记录,确保Worker会触发多次递归。比如创建2500条Mymodel.users,每次删1000,需要2次递归调用(加上手动执行的1次,总共3次perform执行)。
2. 用and_call_original追踪调用
使用RSpec的allow配合and_call_original,既能统计调用次数,又不会阻止原方法执行。
3. 测试代码示例
RSpec.describe Myworker, type: :worker do let(:model) { Mymodel.create! } before do # 生成足够触发递归的测试数据 2500.times { model.users.create! } # 追踪perform_async调用,同时保留原方法逻辑 allow(Myworker).to receive(:perform_async).and_call_original # 如果用Sidekiq,开启inline模式让任务同步执行 Sidekiq::Testing.inline! if defined?(Sidekiq) end it "正确统计递归调用次数" do # 手动执行第一次perform described_class.new.perform(model.id) # 断言perform_async被调用2次(对应两次递归) expect(Myworker).to have_received(:perform_async).exactly(2).times end end
关键说明
and_call_original是核心:它会先让RSpec记录调用,再执行原方法的逻辑,这样递归调用能正常触发,次数统计也不会漏。- 如果用Sidekiq,必须开
inline模式,否则异步任务会放入队列而不立即执行,导致统计不到后续的递归调用。 - 测试后记得清理数据库,避免数据残留影响其他测试。
内容的提问来源于stack exchange,提问作者jansha
相关产品推荐
相关产品推荐

