2

我刚刚安装了 rspec 和 rspec-mocks 但我无法运行最简单的设置

irb(main):001:0> require 'rspec'
=> true
irb(main):004:0> require 'rspec/mocks'
=> false
irb(main):006:0> RSpec::Mocks::setup(Object.new)
NameError: uninitialized constant BasicObject::RSpec
    from /usr/local/Cellar/ruby/1.9.1-p376/lib/ruby/gems/1.9.1/gems/rspec-mocks-2.13.0/lib/rspec/mocks.rb:60:in `block in add_extensions'
    from /usr/local/Cellar/ruby/1.9.1-p376/lib/ruby/gems/1.9.1/gems/rspec-mocks-2.13.0/lib/rspec/mocks.rb:60:in `class_eval'
    from /usr/local/Cellar/ruby/1.9.1-p376/lib/ruby/gems/1.9.1/gems/rspec-mocks-2.13.0/lib/rspec/mocks.rb:60:in `add_extensions'
    from /usr/local/Cellar/ruby/1.9.1-p376/lib/ruby/gems/1.9.1/gems/rspec-mocks-2.13.0/lib/rspec/mocks.rb:11:in `setup'
    from (irb):6
    from /usr/local/Cellar/ruby/1.9.1-p376/bin/irb:12:in `<main>'

我想知道可能出了什么问题,我需要加载其他宝石吗?

4

2 回答 2

2

Jonathan 是在正确的轨道上,但问题的根源是与 1.8.7 不兼容,因为 ::BasicObject 仍然存在于 Ruby 1.9 中。

通过将补丁限制为 Ruby 1.8 来更恰当地指定作者正在修补的内容的正确解决方案:

def method_host
  # On 1.8.7, Object.ancestors.last == Kernel but
  # things blow up if we include `RSpec::Mocks::Methods`
  # into Kernel...not sure why.
  return Object unless defined?(::BasicObject) && RUBY_VERSION =~ /^1\.8\.\d+/

  # MacRuby has BasicObject but it's not the root class.
  return Object unless Object.ancestors.last == ::BasicObject

  ::BasicObject
end
于 2013-05-21T18:08:39.117 回答
0

如果您坚持使用 Ruby 1.9.1,我想我已经为您提供了解决方案,但有一个警告——这有点 hack!

如果您查看您的错误消息,它会说失败位于 /lib/rspec/mocks.rb 的第 60 行。所以让我们看一下:https ://github.com/rspec/rspec-mocks/blob/v2.13.0/lib/rspec/mocks.rb

def add_extensions
  method_host.class_eval { include RSpec::Mocks::Methods } # (line 60)
  Class.class_eval  { include RSpec::Mocks::AnyInstance }
  $_rspec_mocks_extensions_added = true
end

请注意,此私有方法的第一行(第 60 行)正在调用“method_host”。所以让我们看一下私有方法'method_host'的几行:

def method_host
  # On 1.8.7, Object.ancestors.last == Kernel but
  # things blow up if we include `RSpec::Mocks::Methods`
  # into Kernel...not sure why.
  return Object unless defined?(::BasicObject)

  # MacRuby has BasicObject but it's not the root class.
  return Object unless Object.ancestors.last == ::BasicObject

  ::BasicObject
end

您可以看到有几个条件,它有时会返回“Object”,否则会返回“BasicObject”。所以,这让我想知道我们是否不能添加我们自己的条件。

return Object unless defined?(::BasicObject::RSpec)

我们可以通过创建一个文件来测试它,我们称之为 mocks_hack.rb,我们将在其中重新定义“method_host”以包含我们的条件。

module RSpec
  module Mocks
    class << self

    private

      def method_host
        # On 1.8.7, Object.ancestors.last == Kernel but
        # things blow up if we include `RSpec::Mocks::Methods`
        # into Kernel...not sure why.
        return Object unless defined?(::BasicObject)

        # MacRuby has BasicObject but it's not the root class.
        return Object unless Object.ancestors.last == ::BasicObject

        # Jon's hack for Anurag Uniyal
        return Object unless defined?(::BasicObject::RSpec)

        ::BasicObject
      end
    end
  end
end

从 mocks_hack.rb 的当前目录,启动 irb 和以下代码应该“工作”。

require 'rspec'
require './mocks_hack'
RSpec::Mocks::setup(Object.new)

现在,这附带了一个免责声明——这是一个 hack,我不完全理解进行这种更改可能会产生什么影响。希望它有所帮助,并且是一种可行的解决方法。

于 2013-03-08T20:30:41.587 回答