套件未运行之前的RSpec

时间:2014-03-23 00:21:57

标签: ruby-on-rails ruby rspec webmock

我试图在我的测试套件中存根任何外部API调用,但是从不执行before(:suite)。 Webmock总是报告我需要存储maps.googleapis.com,即使还没有运行测试(没有绿点,没有红色F)。

spec_helper.rb:

require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)

...

config.before(:suite) do
    puts "THIS NEVER SHOWS"
    stub_request(:get, "maps.googleapis.com").
      with(headers: {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}).
      to_return(status: 200, body: "", headers: {})
end

geocoder gem最终试图从googleapis.com保存lat / lon,并且Webmock提出错误,说该URL未注册。

编辑:错误代码段:

$ bundle exec rspec spec/factories_spec.rb
/home/jake/.rvm/gems/ruby-2.1.0@global/gems/webmock-1.17.4/lib/webmock/http_lib_adapters/net_http.rb:114:in `request': Real HTTP connections are disabled. Unregistered request: GET http://maps.googleapis.com/maps/api/geocode/json?address=[private]&language=en&sensor=false with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'} (WebMock::NetConnectNotAllowedError)

You can stub this request with the following snippet:

stub_request(:get, "http://maps.googleapis.com/maps/api/geocode/json?address=[private]&language=en&sensor=false").
  with(:headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}).
  to_return(:status => 200, :body => "", :headers => {})

============================================================
    from /home/jake/.rvm/gems/ruby-2.1.0@global/gems/geocoder-1.1.9...

    ...

同样,我强调这与config.before(:each)块中的代码永远不会运行这一事实有关。为什么?因为如果是的话,我可以“提升”WTF'"和' WTF'应出现在控制台输出中,而不是您在上面看到的错误。我只看到了WTF'当我" un-bundle" Webmock的宝石。

1 个答案:

答案 0 :(得分:1)

我通过RSpec测试做了“可爱的事”,在运行时创建测试,具体取决于Factory是否具有属性文件。由于我的工厂/模型的设置方式,当正在读取某个工厂的属性时,正在创建(保存)工厂,因此生成测试的代码块在RSpec的config.before(:suite)之外运行并且WebMock引发了错误。

https://github.com/bblimke/webmock/issues/378

此外,这里特别是我做错了 - 与WebMock无关:

1)在我的factories.rb中,我正在为可能尚不存在的关联调用create()。为什么?因为RSpec给我的错误说“[关联]是空白的”。这样做是因为我有validates_presence_of:association_id而不仅仅是:association。当我使用create()而不是build()时,它“工作”了。当然,到了使用WebMock的时候,我正在创建(并因此保存)调用地理编码器的对象来做这件事。解决方案是修复validates_presence_of以使用正确的属性,并在我的工厂中使用build()而不是create()。

错误示例:

# In spec/factories.rb
factory :review, class: Manager::Review do
    rating 4
    wine { Manager::Wine.first || create(:wine) }
    reviewer { Manager::Reviewer.first || create(:reviewer) }
    date Time.now
    association :referral, referrable_id: 1, referrable_type: Manager::Review, strategy: :build
end

# In app/models/manager/review.rb
validates_presence_of :rating_id, :wine_id, :reviewer_id, :date

好例子:

# In spec/factories.rb
factory :review, class: Manager::Review do
    rating 4
    wine { Manager::Wine.first || build(:wine) }
    reviewer { Manager::Reviewer.first || build(:reviewer) }
    date Time.now
    association :referral, referrable_id: 1, referrable_type: Manager::Review, strategy: :build
end

# In app/models/manager/review.rb
validates_presence_of :rating, :wine, :reviewer, :date

2)FWIW,我告诉地理编码器在pre_save中获取地理编码,而不是像在主页中建议的那样使用after_validate。

另外,你不能在before(:suite)中使用WebMock存根,但它可以在before(:each)之前使用