Я нашел хакерское решение, которое я тестировал на версиях 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
, вероятно, не рекомендуется в производстве.