rspec(4) - request
5574 ワード
テストされていないコードはごろつきです rspec(1) - summary specs(2) - model specs(3) - controller specs(4) - request specs(5) - mock [specs(6) - mailer] [specs(7) - view] [specs(8) - routing] [specs(9) - helper] [specs(10) - factory-girl] [specs(11) - fake other gems] [specs(12) - sidekiq] [specs(13) - db migration] [specs(14) - timecop] [specs(15) - jenkins]
in general, we want to test our api, what should we do in rspec?
what should we do if we want to test external request? a nice gem you can use,
it's so easy to do this, right?
and more. match body match headers auth required
please visit webmock if you wnat to more advange usage
but if we use gems like
firstly, you should have a look at faraday testing, here are some example provided:
test request result
oh, you willl find this gem's test based on webmock. it looks like this.
just do it as webmock.
done!
in general, we want to test our api, what should we do in rspec?
require "rails_helper"
RSpec.describe "User management", :type => :request do
it "creates a User" do
headers = {
"ACCEPT" => "application/json", # This is what Rails 4 accepts
"HTTP_ACCEPT" => "application/json" # This is what Rails 3 accepts
}
lamda do
post "/users", { user: {name: "zql"} }, headers
end.should change(User, :count).by(1)
expect(response.content_type).to eq("application/json")
expect(response).to have_http_status(:created)
user = User.last
user.name.should eq "zql"
# or
expect(user.name).to eq "zql"
end
end
webmock
what should we do if we want to test external request? a nice gem you can use,
webmock
just like this(examples from webmock github): stub_request(:post, "www.example.com").
with(body: "abc", headers: { 'Content-Length' => 3 })
RestClient.post('www.example.com', "data[a]=1&data[b]=five",
content_type: 'application/x-www-form-urlencoded') # ===> Success
RestClient.post('www.example.com', '{"data":{"a":"1","b":"five"}}',
content_type: 'application/json') # ===> Success
RestClient.post('www.example.com', '',
content_type: 'application/xml') # ===> Success
it's so easy to do this, right?
and more.
stub_request(:post, "www.example.com").
with(body: hash_including({data: {a: '1', b: 'five'}}))
RestClient.post('www.example.com', "data[a]=1&data[b]=five&x=1",
:content_type => 'application/x-www-form-urlencoded') # ===> Success
stub_request(:any, "www.example.com").
with(headers:{ 'Header-Name' => 'Header-Value' })
uri = URI.parse('http://www.example.com/')
req = Net::HTTP::Post.new(uri.path)
req['Header-Name'] = 'Header-Value'
res = Net::HTTP.start(uri.host, uri.port) do |http|
http.request(req, 'abc')
end # ===> Success
stub_request(:get, "www.example.com").with(basic_auth: ['user', 'pass'])
# or
# stub_request(:get, "www.example.com").
# with(headers: {'Authorization' => "Basic #{ Base64.strict_encode64('user:pass').chomp}"})
Net::HTTP.start('www.example.com') do |http|
req = Net::HTTP::Get.new('/')
req.basic_auth 'user', 'pass'
http.request(req)
end # ===> Success
please visit webmock if you wnat to more advange usage
but if we use gems like
faraday
or rest-client
, so what should we should in rspec? yeah, we want to mock a api request like mocking a model. here we go. faraday
firstly, you should have a look at faraday testing, here are some example provided:
conn = Faraday::Adapter::Test::Stubs.new do |stub|
stub.get('/ping') { |env| [200, {}, 'hello world!'] }
stub.get('/other_url') { |env| [ 200, {}, 'hello, it's me, another test case' ]}
end
# or
cnnn = Faraday.new do |builder|
builder.adapter :test, stubs do |stub|
stub.get('/test') { |env| [ 200, {}, 'test case' ]}
end
end
test request result
resp = test.get '/ping'
resp.status.should eq 200
resp.body.should eq 'hello world!'
resp = test.get '/other_url'
resp.status.should eq 200
resp.body.should eq 'hello, it's me, another test case'
file upload test
conn = Faraday.new('http://localhost') do |http|
http.request :multipart
http.request :url_encoded
http.adapter :test, stubs do |stub|
stub.post('/upload') { |env| [ 200, {}, {success: true, message: "upload successfully!"} ] }
end
end
payload = { :file => Faraday::UploadIO.new('~/test.jpg', 'image/jpeg') }
resp = conn.post('/upload', payload)
resp.status.should eq 200
data = JSON.parse(resp.body)
data["success"].should eq true
data["message"].should eq "upload_successfully!"
rest-client
oh, you willl find this gem's test based on webmock. it looks like this.
stub_request(:get, "www.example.com").to_return(:body => body, :status => 200)
response = RestClient.get "www.example.com"
expect(response.code).to eq 200
expect(response.body).to eq body
just do it as webmock.
done!