Ruby RSpec Net:HTTP - 如何在模拟响应时测试请求负载是否符合预期
Ruby RSpec Net:HTTP - How to test request payload is as expected while mocking a response
我是一个很!!新的 ruby 和 Rspec 用户正在努力理解如何在模拟来自外部 API 的响应时对 API 请求是否设置了预期的请求负载进行单元测试。我已经使用 Net:HTTP 实现了 API 请求来限制依赖性。
方法正在测试
def lint (url, path, headers={ "Content-Type" => "application/json" }, timeout=10)
if yamlContent = GitLab::Lint::Client::YamlFile.new(path).get_json_content()
uri = URI.parse(url)
req = Net::HTTP::Post.new(uri, headers)
req.body = { content: yamlContent }.to_json
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
response = https.request(req)
case response
when Net::HTTPSuccess
puts "Linting request successful"
return JSON.parse(response.body)
when Net::HTTPUnauthorized
abort("#{response.message}: invalid token in api request?")
when Net::HTTPServerError
abort('error' => "#{response.message}: server error, try again later?")
when Net::HTTPBadRequest
puts "Bad request..." + req.body
abort("#{response.message}: bad api request?")
when Net::HTTPNotFound
abort("#{response.message}: api request not found?")
else
puts "Failed validation\nJSON payload :: #{req.body}\nHTTP Response: #{response.message}"
abort("#{response.message}: failed api request?")
end
else
abort("\nLint request failed, problem encountered reading yaml file")
end
end
RSpec 测试
require "gitlab/lint/client/api"
RSpec.describe Gitlab::Lint::Client::Api do
describe "#initialize" do
it "initialises" do
api = Gitlab::Lint::Client::Api.new
expect(api).to be_instance_of(Gitlab::Lint::Client::Api)
end
end
describe "#lint" do
before(:each) do
@response = instance_double(Net::HTTPSuccess, body: @response_body, message: 'OK')
@response_body = { 'status' => 'valid', 'errors' => [] }.to_json
@request_mock = instance_double(Net::HTTP::Post)
allow(@request_mock).to receive(:[]=)
allow(@request_mock).to receive(:body=)
allow(Net::HTTP::Post).to receive(:new).and_return(@request_mock)
@http_client_mock = instance_double(Net::HTTP)
allow(@http_client_mock).to receive(:use_ssl=)
allow(@http_client_mock).to receive(:verify_mode=)
allow(@http_client_mock).to receive(:request)
allow(Net::HTTP).to receive(:new).and_return(@http_client_mock)
allow(@http_client_mock).to receive(:request).with(@request_mock).and_return(@response)
@endpoint_url = 'http://gitlab.com'
@fileName='test.yml'
allow(File).to receive(:exist?).with(@fileName).and_return(true)
allow(File).to receive(:readable?).with(@fileName).and_return(true)
allow(YAML).to receive(:load_file).with(@fileName).and_return("image: ruby:latest")
end
it "lints successfully" do
# for a valid case we want:
# - test that the request body was set with content as expected
# - simulate the response to be { status: "valid", "errors": []}
api = Gitlab::Lint::Client::Api.new
api.lint(@endpoint_url, @fileName)
expect(@request_mock.body).to have_received({ content: {'image' => 'ruby:latest'} }.to_json)
end
end
end
运行 测试给出以下错误输出:
Gitlab::Lint::Client::Api
#initialize
initialises
#lint
OK: failed api request? # this output signifies that the case structure has not recognised the response as a HTTPSuccess instance
在我的 lint 测试方法的案例结构中,响应未被视为 Net::HTTPSuccess 的实例。如何模拟 Net::HTTPSuccess 实例?
一种流行的方法称为 VCR。您可以在项目网站上找到大量文档和 RailsCast。基本上,它是这样工作的:
- 您将 VCR 设置为“记录模式”。
- 您向真实后端发出请求。 VCR 记录请求和响应。
- 您将 VCR 设置为“回放”模式。
- 当您 运行 测试时,您可以使用 VCR 对请求和响应做出断言(换句话说,它符合您的期望)。
这是一种验证 HTTP 请求是否完全按照您的要求执行的可靠方法。
我是一个很!!新的 ruby 和 Rspec 用户正在努力理解如何在模拟来自外部 API 的响应时对 API 请求是否设置了预期的请求负载进行单元测试。我已经使用 Net:HTTP 实现了 API 请求来限制依赖性。
方法正在测试
def lint (url, path, headers={ "Content-Type" => "application/json" }, timeout=10)
if yamlContent = GitLab::Lint::Client::YamlFile.new(path).get_json_content()
uri = URI.parse(url)
req = Net::HTTP::Post.new(uri, headers)
req.body = { content: yamlContent }.to_json
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
response = https.request(req)
case response
when Net::HTTPSuccess
puts "Linting request successful"
return JSON.parse(response.body)
when Net::HTTPUnauthorized
abort("#{response.message}: invalid token in api request?")
when Net::HTTPServerError
abort('error' => "#{response.message}: server error, try again later?")
when Net::HTTPBadRequest
puts "Bad request..." + req.body
abort("#{response.message}: bad api request?")
when Net::HTTPNotFound
abort("#{response.message}: api request not found?")
else
puts "Failed validation\nJSON payload :: #{req.body}\nHTTP Response: #{response.message}"
abort("#{response.message}: failed api request?")
end
else
abort("\nLint request failed, problem encountered reading yaml file")
end
end
RSpec 测试
require "gitlab/lint/client/api"
RSpec.describe Gitlab::Lint::Client::Api do
describe "#initialize" do
it "initialises" do
api = Gitlab::Lint::Client::Api.new
expect(api).to be_instance_of(Gitlab::Lint::Client::Api)
end
end
describe "#lint" do
before(:each) do
@response = instance_double(Net::HTTPSuccess, body: @response_body, message: 'OK')
@response_body = { 'status' => 'valid', 'errors' => [] }.to_json
@request_mock = instance_double(Net::HTTP::Post)
allow(@request_mock).to receive(:[]=)
allow(@request_mock).to receive(:body=)
allow(Net::HTTP::Post).to receive(:new).and_return(@request_mock)
@http_client_mock = instance_double(Net::HTTP)
allow(@http_client_mock).to receive(:use_ssl=)
allow(@http_client_mock).to receive(:verify_mode=)
allow(@http_client_mock).to receive(:request)
allow(Net::HTTP).to receive(:new).and_return(@http_client_mock)
allow(@http_client_mock).to receive(:request).with(@request_mock).and_return(@response)
@endpoint_url = 'http://gitlab.com'
@fileName='test.yml'
allow(File).to receive(:exist?).with(@fileName).and_return(true)
allow(File).to receive(:readable?).with(@fileName).and_return(true)
allow(YAML).to receive(:load_file).with(@fileName).and_return("image: ruby:latest")
end
it "lints successfully" do
# for a valid case we want:
# - test that the request body was set with content as expected
# - simulate the response to be { status: "valid", "errors": []}
api = Gitlab::Lint::Client::Api.new
api.lint(@endpoint_url, @fileName)
expect(@request_mock.body).to have_received({ content: {'image' => 'ruby:latest'} }.to_json)
end
end
end
运行 测试给出以下错误输出:
Gitlab::Lint::Client::Api
#initialize
initialises
#lint
OK: failed api request? # this output signifies that the case structure has not recognised the response as a HTTPSuccess instance
在我的 lint 测试方法的案例结构中,响应未被视为 Net::HTTPSuccess 的实例。如何模拟 Net::HTTPSuccess 实例?
一种流行的方法称为 VCR。您可以在项目网站上找到大量文档和 RailsCast。基本上,它是这样工作的:
- 您将 VCR 设置为“记录模式”。
- 您向真实后端发出请求。 VCR 记录请求和响应。
- 您将 VCR 设置为“回放”模式。
- 当您 运行 测试时,您可以使用 VCR 对请求和响应做出断言(换句话说,它符合您的期望)。
这是一种验证 HTTP 请求是否完全按照您的要求执行的可靠方法。