在寫測試的時後,一定會有第三方服務或是會打向外部api的時候,如果不想讓他真的去打外部api怕速度過慢的等等問題就可以使用 webmock 。
webmock 可以偽裝 HTTP 來確保我們在測試時不會真的發出請求。
# add to your Gemfile
group :test do
gem "webmock"
end
# spec_helper.rb
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
參考範例:
在還沒有禁用 api 之前會通過
context "get github api" do
it 'repo on GitHub' do
uri = URI('https://api.github.com/repositories')
response = Net::HTTP.get(uri)
expect(response).to be_an_instance_of(String)
end
end
如果在測試之前加上
before(:all) { WebMock.disable_net_connect! }
after(:all) { WebMock.allow_net_connect! }
context "get github api" do
it 'repo on GitHub' do
uri = URI('https://api.github.com/repositories')
response = Net::HTTP.get(uri)
expect(response).to be_an_instance_of(String)
end
end
此時會出現貼心的錯誤提示告訴你該如果撰寫
Failure/Error: response = Net::HTTP.get(uri)
WebMock::NetConnectNotAllowedError:
Real HTTP connections are disabled. Unregistered request: GET https://api.github.com/repositories with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Host'=>'api.github.com', 'User-Agent'=>'Ruby'}
You can stub this request with the following snippet:
stub_request(:get, "https://api.github.com/repositories").
with(
headers: {
'Accept'=>'*/*',
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Host'=>'api.github.com',
'User-Agent'=>'Ruby'
}).
to_return(status: 200, body: "", headers: {})
這時來修改一下
context "github api" do
it 'repo on GitHub' do
uri = URI('https://api.github.com/repositories')
stub_request(:get, uri).
with(
headers: {
'Accept'=>'*/*',
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Host'=>'api.github.com',
'User-Agent'=>'Ruby'
}).
to_return(status: 200, body: "", headers: {})
response = Net::HTTP.get(uri)
expect(response).to be_an_instance_of(String)
end
end
這時確實已經將 api stub 了,且測試也會通過
參考來源:
WebMock
How to Stub External Services in Tests