我正在尝试存根某些类的任何实例。我需要存根fetch
方法,它用一些数据填充自己。
如何访问self
变量,修改变量并返回fetch
方法?
MyObject.any_instance.stub(:fetch) { self }
不会返回MyObject
个实例。
也许,在这种情况下,模拟更有用。不幸的是,我还没有理解它们。
答案 0 :(得分:13)
有一个open rspec-mocks issue来解决这个问题。我希望能够在某些时候解决这个问题,但是以一种不会破坏使用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
基本上,我们通过挂钩any_instance
来模拟MyObject.new
,以便我们可以在每个实例化的新实例上存根fetch
。
所有这一切,“听取你的测试”很重要,而且,当某些事情难以测试时,请考虑一下你的设计,而不是立即使用像any_instance
这样的电动工具。你原来的问题并没有给我足够的背景来推测你的设计,但是当我面临需要这样做的时候,它肯定是我要开始的。
答案 1 :(得分:1)
据我所知,出于某种原因,这似乎不可能。我检查了当前的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
看起来,块只是由它自己调用而不是通过instance_eval
调用。也许还有另一种技术可以实现你想要的,毕竟我毕竟不是RSpec专家。