我试图在我的测试套件中存根任何外部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'应该出现在控制台输出中,而不是您上面看到的错误。当我"解绑定"Webmock gem时,我只看到"WTF"。
我在RSpec测试中做了一些"可爱的事情",在运行时根据工厂是否有一个属性是文件创建测试。由于我的工厂/模型的设置方式,当某个工厂的属性被读取时,正在创建(保存)工厂,因此生成测试的代码块在RSpec的config.before(:suite)之外运行,WebMock会引发错误。
https://github.com/bblimke/webmock/issues/378此外,以下是我做错的地方——与WebMock无关:
在我的工厂。我正在调用create()来创建可能还不存在的关联。为什么?因为RSpec给我的错误是"[关联]是空白的"。它这样做是因为我有validates_presence_of:association_id而不是:association。当我使用create()而不是build()时,它"工作"。当然,当使用WebMock时,我正在创建(并因此保存)调用geocoder的对象来完成它的工作。解决方案是修复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) fww,我告诉geocoder获取地理代码前_save,而不是后_validate,就像它建议在他们的主页。
同样,您不能在before(:suite)中使用WebMock存根,但它可以在before(:each)