ruby-on-rails - 使用 RSPEC 和 ROR 在 rails 控制器中存根 api 调用
问题描述
我有以下导轨控制器
class FoodsController < ApplicationController
before_action :set_food, only: [:show, :update, :destroy]
# GET /foods/1
def show
#render json: @food
render json:
{
"barcode": @food.barcode,
"product": @food.product
}
end
private
# Use callbacks to share common setup or constraints between actions.
def set_food
#@food = Food.find(params[:id])
code = params[:id]
product = Openfoodfacts::Product.get(code, locale: 'fr')
@food = Food.create_with(product: product.product_name).find_or_create_by(barcode: code)
end
# Only allow a list of trusted parameters through.
def food_params
params.require(:food).permit(:barcode, :product)
end
end
我有以下 rspec 测试
require 'rails_helper'
RSpec.describe FoodsController, type: :request do
include_context 'openfood_context'
let(:headers) { { Authorization: "Token #{TokenAuth::API_TOKEN}" } }
let(:response_body) { JSON.parse(response.body) }
let(:given_product) { response_body['product'] }
let(:given_barcode) { response_body['barcode'] }
before do
get food_path(id: barcode), headers: headers
expect(response).to have_http_status(:ok)
end
it 'returns the product name' do
expect(given_product).to eq product
end
it 'returns the barcode' do
expect(given_barcode).to eq barcode
end
end
这些页面有效,当我点击 foods/099482476885 路线时,我得到这张图片中的输出,在此处输入图像描述。但是当我运行规范时,我得到下面的错误
1) FoodsController returns the product name
Failure/Error: product = Openfoodfacts::Product.get(code, locale: 'fr')
WebMock::NetConnectNotAllowedError:
Real HTTP connections are disabled. Unregistered request: GET https://fr.openfoodfacts.org/api/v0/produit/049000061017.json with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}
You can stub this request with the following snippet:
stub_request(:get, "https://fr.openfoodfacts.org/api/v0/produit/049000061017.json").
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: {})
============================================================
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/net_http.rb:114:in `request'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/net_http.rb:123:in `start_without_connect'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/webmock-3.13.0/lib/webmock/http_lib_adapters/net_http.rb:150:in `start'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/openfoodfacts-0.6.0/lib/openfoodfacts/product.rb:25:in `get'
# ./app/controllers/foods_controller.rb:23:in `set_food'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/rack-2.2.3/lib/rack/etag.rb:27:in `call'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/rack-2.2.3/lib/rack/conditional_get.rb:27:in `call'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/rack-2.2.3/lib/rack/head.rb:12:in `call'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.1.3.2/lib/rails/rack/logger.rb:37:in `call_app'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.1.3.2/lib/rails/rack/logger.rb:26:in `block in call'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.1.3.2/lib/rails/rack/logger.rb:26:in `call'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/rack-2.2.3/lib/rack/runtime.rb:22:in `call'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/rack-2.2.3/lib/rack/sendfile.rb:110:in `call'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/railties-6.1.3.2/lib/rails/engine.rb:539:in `call'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/rack-test-1.1.0/lib/rack/mock_session.rb:29:in `request'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/rack-test-1.1.0/lib/rack/test.rb:266:in `process_request'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/rack-test-1.1.0/lib/rack/test.rb:119:in `request'
# ./spec/requests/foods_controller_spec.rb:13:in `block (2 levels) in <top (required)>'
# /home/ubuntu/.rvm/gems/ruby-2.6.3/gems/webmock-3.13.0/lib/webmock/rspec.rb:37:in `block (2 levels) in <top (required)>'
然后我尝试将以下存根添加到 spec/spec_helper.rb 但得到与图片中的错误类似的错误。我该如何解决这个规范问题?
config.before(:each) do
stub_request(:get, /api.openfoodfacts.org/).
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: "stubbed response", headers: {})
end
解决方案
您正在将请求存根,api.openfoodfacts.org
但您分享了一个错误,抱怨向fr.openfoodfacts.org
.
Webmock 将阻止您规范中的所有外部请求(这是设计使然),因此当您将请求存根时foo
,请特别注意错误消息是否更改为Unregistered request: bar
. 你需要把它们全部存根,
或模拟Openfoodfacts::Product
自身:
allow(Openfoodfacts::Product).to receive(:get).and_return(...)
(这将取消禁用此类的“正常”行为,并且任何调用都会返回您告诉它返回的内容。
第三种选择可能是使用VCR gem,它可以记录请求和响应,然后为您模拟它们。
每个解决方案都有其优点和缺点,(我认为)超出了这个问题的范围。
推荐阅读
- javascript - Recharts 条形图 - 有条件地仅在堆叠条形图中的某些条形上显示标签
- bash - 如何删除文件末尾的这个特殊字符
- javascript - Node Js NPM PDFkit和Voilab pdf表格,生成表格后pdfkit段落错误
- shopify - Shopoify 的 Polaris 是用于样式主题还是仅用于创建自定义/公共应用程序?
- javascript - 在 JavaScript 中使用带有变量的方法
- sql - 在 SQL 中的 FOR JSON 输出中防止双重转义 JSON
- python - Matplotlib.plot() 不会正确渲染绘图。改为制作某种网络
- javascript - 将文档添加到 Firestore 中不存在的子集合
- http - 使用 curl 进行 nutch RESTapi 调用时出错
- python - 如何在不使用 json 库或在字典或列表中没有任何其他库的情况下读取 json 文件?