Ruby + Rspec + OpenStruct奇怪的行为

时间:2014-10-02 00:00:51

标签: ruby rspec rspec3

因此,我在测试ruby类时遇到了这种奇怪的行为。我顺便使用rspec 3来测试它。

Class Foo有一个方法&f; fetch_object'它叫做'找到'从类Bar中检索对象的方法,而不是调用方法' fail'来自获取的对象。

所谓奇怪的行为发生在我希望收到方法“失败”的时候。一旦收到,但如果我更改了' faill'它就像一个魅力:S

这是戏剧:

require 'ostruct'

class Foo

  def fetch_object
    foobar = Bar.find
    foobar.fail
  end

end

class Bar

  def self.find
    OpenStruct.new(name: 'Foo Bar')
  end

end

describe Foo do

  subject { Foo.new }

  let(:foo) { OpenStruct.new() }

  before do
    expect(Bar).to receive(:find).and_return(foo)
  end

  it 'fetch object with name' do
    expect(foo).to receive(:fail)
    subject.fetch_object
  end

end

1 个答案:

答案 0 :(得分:1)

我怀疑它是因为你正在设置对象的期望,这种行为取决于method_missingOpenStruct)。

因为这个原因我不想把它作为模拟,我会使用常规模拟(并且规范会通过):

let(:foo) { double('foobar') }

您正在此处进行测试,如果返回的对象(Bar.find的结果)将收到预期的消息,而不会进入实现细节。

设置像ostruct这样的动态类的期望可能会导致奇怪的结果。似乎在某些时候调用Kernel#fail方法,因此,将名称更改为faill或任何其他尚未采用的方法"通过内核将使它工作。

其他解决方案是monkeypatching OpenStruct以避免调用method_missing

class OpenStruct
  def fail
    true
  end
end

class Foo

  def fetch_object
    foobar = Bar.find
    foobar.fail
  end

end

class Bar

  def self.find
    OpenStruct.new(name: 'Foo Bar')
  end

end

describe Foo do

  subject { Foo.new }

  let(:foo) { OpenStruct.new }

  before do
    expect(Bar).to receive(:find).and_return(foo)
  end

  it 'fetch object with name' do
    expect(foo).to receive(:fail)
    subject.fetch_object
  end

end

但我不知道你为什么要那样做;)

更多信息:Doubles and dynamic classess