Feature: test randomness
In order to make some code testable
As a developer
I want Array#sample to become Array#first
如果可以访问Klass.any_instance.stub块中的实例,那么这是可能的。像这样:
Array.any_instance.stub(:sample) { instance.first }
但是那个afaik是不可能的。
无论如何,想要的场景!
答案 0 :(得分:2)
我找到了一个hacky解决方案,我在rspec版本2.13.1和2.14.4上测试过。你需要binding_of_caller
gem。
Helper方法 - 这应该可以通过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
。
答案 1 :(得分:0)
对于那些现在遇到困难的人来说,Rspec 3通过传递给stub
的块中的第一个参数实现了这个功能:
RSpec::Mocks.configuration.yield_receiver_to_any_instance_implementation_blocks = true # I believe this is the default
Array.any_instance.stub(:sample) { |arr| arr.first }
我发现了here。