Ruby 1.9.3, RSpec 2.13.0, WebMock 1.17.4, Rails 3
我正在为公司应用程序编写测试。有问题的控制器显示客户拨打的呼叫表,并允许排序/过滤选项。
编辑 测试失败,因为使用我的当前设置,路径不会呈现,因为recorder_server
要么未在本地运行,要么未正确设置。也请帮忙。
A Errno::ECONNREFUSED occurred in recordings#index:
Connection refused - connect(2)
/usr/local/lib/ruby/1.9.1/net/http.rb:763:in `initialize'
-------------------------------
Request:
-------------------------------
* URL : http://www.recorder.example.com:8080/recorded_calls
* IP address: 127.0.0.1
* Parameters: {"controller"=>"recordings", "action"=>"index"}
* Rails root: /var/www/rails/<repository>
- 发出调用时,其数据将加入由外部 API 创建的 xml 文件,称为记录器
- 录制控制器获取 xml 文件,并将其解析为哈希。
- 当您访问关联的路径时,您会看到哈希的结果 - 一个已放置调用的表,其属性和排序/筛选参数。
这是我到目前为止的规格。
require 'spec_helper'
include Helpers
feature 'Exercise recordings controller' do
include_context "shared admin context"
background do
canned_xml = File.open("spec/support/assets/canned_response.xml").read
stub_request(:post, "http://recorder.example.com:8080/recorder/index").
with(body: {"durations"=>["1"], "durations_greater_less"=>["gt"], "filter_from_day"=>"29", "filter_from_hour"=>"0", "filter_from_minute"=>"0", "filter_from_month"=>"12", "filter_from_year"=>"2014", "filter_prefix"=>true, "filter_to_day"=>"29", "filter_to_hour"=>"23", "filter_to_minute"=>"59", "filter_to_month"=>"12", "filter_to_year"=>"2014"}, # "shared_session_id"=>"19f9a08807cc70c1bf41885956695bde"},
headers: {'Accept'=>'*/*', 'Content-Type'=>'application/x-www-form-urlencoded', 'User-Agent'=>'Ruby'}).
to_return(status: 200, body: canned_xml, headers: {})
uri = URI.parse("http://recorder.example.com:8080/recorder/index")
visit recorded_calls_path
end
scenario 'show index page with 1 xml result' do
#page.save_and_open_page
expect(title).to eq("Recorded Calls")
end
end
这是录音控制器
class RecordingsController < ApplicationController
# before_filter options
def index
test_session_id = request.session_options[:id]
#Make request to recording app for xml of files
uri = URI.parse("http://#{Rails.application.config.recorder_server}:#{Rails.application.config.recorder_server_port}/recorder/index")
http = Net::HTTP.new(uri.host, uri.port)
xml_request = Net::HTTP::Post.new(uri.request_uri)
xml_request_data = Hash.new
# sorting params
xml_request_data[:shared_session_id] = request.session_options[:id]
xml_request.set_form_data(xml_request_data)
response = http.request(xml_request)
if response.class == Net::HTTPOK
@recordings_xml = XmlSimple.xml_in(response.body)
@recordings_sorted = @recordings_xml["Recording"].sort { |a,b| Time.parse("#{a["date"]} #{a["time"]}") <=> Time.parse("#{b["date"]} #{b["time"]}") } unless @recordings_xml["Recording"].nil?
else @recordings_xml = Hash.new
end
end
# other defs
end
任何和所有的建议都非常感谢。谢谢。
我如何配置 WebMock
我正在B-Seven和一系列评论的帮助下回答我自己的问题。逐个文件,我将列出为正确使用 WebMock 所做的更改。
- 将 WebMock 添加到
group :test, :development
下的Gemfile
。-
bundle install
解析依赖关系 - 我目前的设置包括Ruby 1.9.3,Rails 2.13.0,WebMock 1.17.4
-
-
安装程序
spec_helper.rb
禁用"真正的HTTP连接"。(这是后来在这个令人费解的过程中收到的回溯错误。据我了解,这允许所有"真正的连接"转化为localhost
连接并离线工作......这很棒,因为理想情况下,我不希望外部应用程序的服务器同时运行。require 'webmock/rspec' WebMock.disable_net_connect!(allow_localhost: true)
-
在我的
test.rb
环境文件中,recorder_server
和port
的配置被注释掉了......如果未注释,控制器将引发一个异常,指出未初始化的常量。我使用测试服务器/端口(用公司名称代替example
)作为规范存根的布局。 -
在
recordings_controller_spec.rb
,我已经想出了如何制作一个预制的XML响应。通过上述这些更改,我的规范能够在外部辅助应用程序上正确存根响应,并使用此类响应正确呈现与正在测试的控制器关联的视图。require 'spec_helper' include Helpers feature "Exercise recordings_controller" do include_context "shared admin context" # A background is currently not used, because I have 3 scenario types... No xml # results, 1 result, and 2 results. I will later DRY this out with a background, # but the heavy lifting is over, for now. scenario "show index page with 1 xml result" do canned_xml_1 = File.open("spec/support/assets/canned_response_1.xml").read stub_request(:post, "http://recorder.example.com:8080/recorder/index"). with(headers: {'Accept'=>'*/*', 'User-Agent'=>'Ruby'}). to_return(status: 200, body: canned_xml_1, headers: {}) uri = URI.parse("http://recorder.example.com:8080/recorder/index") visit recorded_calls_path title.should == "Recorded Calls" page.should have_content("Search Results") page.should have_content("Inbound", "5551230000", "175", "December 24 2014", "12:36:24", "134") end end
有帮助的建议/资源
- 根据B-Seven对我最初问题的建议(请参阅修订版),我最初是在
localhost:3000
存根。他说这是不正确的。经过进一步的研究,我同意,因为使用 WebMock 的存根通常是为外部 http 连接保留的。 - 在他回答后的评论中,B-Seven列出了要参考的文章。我将列出对我帮助最大的那些。
- http://robots.thoughtbot.com/how-to-stub-external-services-in-tests
- http://railscasts.com/episodes/275-how-i-test
- https://github.com/bblimke/webmock
- http://www.agileventures.org/articles/testing-with-rspec-stubs-mocks-factories-what-to-choose
- 读取错误生成的回溯非常重要。我花了这么长时间才弄清楚如何嘲笑主要是读错了它们。从我的问题中可以看出,我提出了一个
:get
存根请求。一位同事指出,回溯建议使用:post
。那是让我的规格通过的最后一件作品。 - 我决定不输入配置变量作为我的存根请求,因为这会导致长行代码。相反,这就是为什么我需要在
test.rb
中取消注释掉这些配置。
你为什么要存根本地主机?我想你想
stub_request(:get, "http://#{Rails.application.config.recorder_server}:#{Rails.application.config.recorder_server_port}/recorder/index").