Rspec,你可以存根一个对象上不存在的方法(或者模拟一个可以采用任何方法的对象)吗?

时间:2015-06-19 18:58:46

标签: ruby-on-rails ruby-on-rails-4 rspec rspec-rails stub

这可能听起来像一个非常基本的问题......所以让我解释一下背景。我正在从Stripe中检索一个事件,但就此而言,这适用于我考虑过的其他事情。

我在Stripe对象中需要的数据是埋藏的,所以我必须做event.data.object.date.lines.first.id。我不确定如何模拟/存根...

我能想到的唯一方法就是创建一个模拟Stripe事件对象的假模型(在本例中对我来说,请记住Stripe事件不能由用户创建)。然后我可以模仿那个假模型。但这真的是这样做的吗?是否有某种方法我可以使用Rspec来存储整个shebang并说event.data.object.date.lines.first.id只要它出现在哪里就应该重新调用1

哦,还有...如果没有,事实证明我必须创建一个假模型...提示非常感谢,因为现在我认为这个“假”模型需要多层儿童,并且完全不值得花时间投资。

2 个答案:

答案 0 :(得分:1)

在Stripe的这种情况下,我选择使用库进行模拟,而不是使用RSpec创建存根。我已经使用并强烈建议stripe-ruby-mock

这种方法的好处是,您可以更密切地嘲笑Stripe的实际工作方式,并且switch to the actual stripe test api very easily可以。

答案 1 :(得分:0)

RSpec没有提供访问被测元素的特殊机制,所以是的,您需要以某种方式stub id方法并让它返回您想要的任何内容(例如1)。

为此,您必须有办法访问测试中的event对象,以便您可以使用data方法存根。一旦你可以访问它,你就可以使用RSpec的receive_message_chain匹配器来指定方法的顺序,如果被调用,你将返回1

如果有一些公共Strip方法,您可以模拟为事件返回double,这将是最简单的方法。

如果无法做到这一点,您可以确定event的类,并使用allow_any_instance_of方法来存根data方法。结果模拟如下,假设Foo是您关注的event对象的类:

allow_any_instance_of(Foo)).to receive_message_chain(
  :data, :object, :date, :lines, :first, :id).and_return(1)

这是一个通过的测试:

module Stripe
  class Event ; end
end
describe 'stack overflox example' do
  it 'should pass' do
    event = Stripe::Event.new
    expect(event).to receive_message_chain(:data, :object, :date, :lines, :first, :id).and_return(23)
    expect(event.data.object.date.lines.first.id).to eq(23)
  end
end