3

I'm trying to stub any external API calls in my test suite, but the before(:suite) is never executed. Webmock always reports that I need to stub the maps.googleapis.com even though no tests have been run yet (no green dots, no red Fs).

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

The geocoder gem ends up trying to save the lat/lon from googleapis.com and an error is raised by Webmock saying that the URL is unregistered.

EDIT: Error snippet:

$ 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...

    ...

Again, I'll stress that this has to do with the fact that the code in the config.before(:each) block is never run. Why? Because if it was, I could "raise 'WTF'" and 'WTF' should appear in the console output instead of the error you see above. I only see 'WTF' when I "un-bundle" the Webmock gem.

4

1 回答 1

1

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

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

此外,这就是我做错的事情——与 WebMock 无关:

1) 在我的 factory.rb 中,我为可能尚不存在的关联调用 create()。为什么?因为 RSpec 给我错误说“[association] 是空白的”。这样做是因为我有 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,我告诉地理编码器获取地理编码 before_save,而不是 after_validate 就像它在他们的主页上建议的那样。

此外,您不能在 before(:suite) 中使用 WebMock 存根,但它在 before(:each) 中有效

于 2014-03-23T23:35:07.580 回答