RSpec any_instance返回self

Kuk*_*nin 15 ruby rspec

我正在尝试存根某些类的任何实例.我需要存根fetch方法,用一些数据填充自己.

如何访问self变量,修改变量并返回fetch方法?

MyObject.any_instance.stub(:fetch) { self }
Run Code Online (Sandbox Code Playgroud)

不返回MyObject实例.

也许,在这种情况下,模拟更有用.不幸的是,我还没有理解它们.

Myr*_*ton 13

有一个开放的rspec-mocks问题来解决这个问题.我希望能够在某些时候解决它,但是以一种不破坏any_instance与块实现一起使用的现有规范套件的方式添加它并不简单,因为我们将开始产生一个额外的参数(例如对象实例) ).

总的来说,any_instance在某些情况下可以派上用场,但它有点嗅觉,如果你能找到一种模拟或存根单个实例的方法,你通常会遇到更少的问题.

这是一个我尚未测试但应该工作的解决方法:

orig_new = MyObject.method(:new)
MyObject.stub(:new) do |*args, &block|
  orig_new.call(*args, &block).tap do |instance|
    instance.stub(:fetch) { instance }
  end
end
Run Code Online (Sandbox Code Playgroud)

本质上,我们any_instance通过挂钩来模拟这里,MyObject.new以便我们可以存根fetch实例化的每个新实例.

所有这一切,重要的是"倾听你的测试",当一些事情很难测试时,考虑一下你的设计,而不是立即使用电动工具any_instance.你原来的问题并没有为我提供足够的背景来推测你的设计,但是当我面临需要这样做时,它肯定是我要开始的地方.


fre*_*oma 2

据我所知,出于某种原因,这似乎不可能。我检查了当前的rspec-mocks实现,实际调用存根实现的方法似乎如下:

# lib/rspec/mocks/message_expectation.rb:450
def call_implementation(*args, &block)
    @implementation.arity == 0 ? @implementation.call(&block) : @implementation.call(*args, &block)
end
Run Code Online (Sandbox Code Playgroud)

看起来,该块只是由其本身调用,而不是通过instance_eval. 也许还有另一种技术可以实现你想要的,毕竟我无论如何都不是 RSpec 专家。