Rspec:访问 Klass.any_instance.stub 块内的实例

发布于 2024-11-11 04:36:54 字数 332 浏览 4 评论 0原文

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 }

但是据我所知这是不可能的。

无论如何,想要场景!

Feature: test randomness
    In order to make some code testable
    As a developer
    I want Array#sample to become Array#first

It would be possible if one could access instance inside Klass.any_instance.stub block. Something like this:

Array.any_instance.stub(:sample) { instance.first }

But that afaik is not possible.

Anyway, scenarios wanted!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

故笙诉离歌 2024-11-18 04:36:54

我找到了一个 hacky 解决方案,我已经在 rspec 版本 2.13.1 和 2.14.4 上进行了测试。您将需要 binding_of_caller gem。

辅助方法 - 这应该可以由您的 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

I found a hacky solution, which I've tested on rspec versions 2.13.1 and 2.14.4. You'll need the binding_of_caller gem.

Helper method - this should be callable by your rspec example:

# 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

Then in your example:

Array.any_instance.stub(:sample) do
  instance = any_instance_receiver
  instance.first
end

I've set a limit on the stack searching, to avoid searching a huge stack. I don't see why you'd need to increase it, since it should always be around cur_idx == 8.

Note that using binding_of_caller is probably not recommended in production.

何以笙箫默 2024-11-18 04:36:54

对于那些现在遇到这个问题的人,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 }

我发现了这个

For those stumbling across this now, Rspec 3 implements this functionality via the first argument in the block passed to 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 }

I found this here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文