art*_*ave 5 ruby tdd bdd rspec
Feature: test randomness
In order to make some code testable
As a developer
I want Array#sample to become Array#first
Run Code Online (Sandbox Code Playgroud)
如果有人可以访问Klass.any_instance.stub块中的实例,那么这是可能的.像这样的东西:
Array.any_instance.stub(:sample) { instance.first }
Run Code Online (Sandbox Code Playgroud)
但是那个afaik是不可能的.
无论如何,想要的场景!
我找到了一个 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
Run Code Online (Sandbox Code Playgroud)
然后在你的例子中:
Array.any_instance.stub(:sample) do
instance = any_instance_receiver
instance.first
end
Run Code Online (Sandbox Code Playgroud)
我对堆栈搜索设置了限制,以避免搜索巨大的堆栈。我不明白为什么你需要增加它,因为它应该始终存在cur_idx == 8。
请注意,binding_of_caller在生产中可能不建议使用。