我發現了一個hacky解決方案,我在rspec版本2.13.1和2.14.4上測試過。你需要binding_of_caller
寶石。
助手方法 - 這應該由你的rspec的例子可調用:
# must be called inside stubbed implementation
def any_instance_receiver(search_limit = 20)
stack_file_str = 'lib/rspec/mocks/any_instance/recorder.rb:'
found_instance = nil
# binding_of_caller's notion of the stack is different from caller(), so we need to search
(1 .. search_limit).each do |cur_idx|
frame_self, stack_loc = binding.of_caller(cur_idx).eval('[self, caller(0)[0]]')
if stack_loc.include?(stack_file_str)
found_instance = frame_self
break
end
end
raise "instance not found" unless found_instance
return found_instance
end
然後在你的榜樣:
Array.any_instance.stub(:sample) do
instance = any_instance_receiver
instance.first
end
我設置堆棧搜索的限制,以避免搜索一巨大的堆棧。我不明白你爲什麼需要增加它,因爲它應該總是在cur_idx == 8
左右。
請注意,在生產中可能不推薦使用binding_of_caller
。