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>

当调用被放置时,它的数据连接一个xml文件,该文件由一个名为recorder的外部api创建
recordingcontroller获取xml文件,并将其解析为散列。
当您访问关联的路径时,您将看到散列的结果——一个包含放置的调用、它们的属性和sort/filter参数的表。
这是我目前的规格。
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添加到Gemfile下的group :test, :development
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_serverport的配置被注释掉…如果保持未注释状态,控制器将引发一个异常,指出未初始化的常量。我使用测试服务器/端口(用公司名称替换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-7列出了可参考的文章。我会列出那些对我帮助最大的。
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
读取由错误生成的回溯非常重要。我花了很长时间才弄明白如何嘲笑,主要是看错了。正如您从我的问题中看到的,我提出了一个存根请求。一位同事指出,backtrace建议使用:get。这是最后一个让我的规格通过。
我决定不把配置变量作为存根请求输入,因为这会导致代码行太长。相反,这就是我需要在:post中取消注释这些配置的原因。

07-26 09:35