除非我插入它,否则Rails不会呈现RestClient异常体

时间:2016-07-18 18:46:47

标签: ruby-on-rails ruby

我在尝试围绕rails控制器编写测试时遇到了一个非常奇怪的问题。 控制器使用RestClient从另一台服务器获取信息。如果第二个服务器返回错误响应,我想将该错误消息转发给客户端。

控制器:

def callback_submit
  begin
    response = RestClient.post(...)
    render json: response
  rescue RestClient::BadRequest => e
    render status: :bad_request, json: { error: e.response.body }
  end
end

然后我对此进行了一次rspec测试:

  it 'returns a failure message' do
    stub_request( :post, 'http://...' ).to_return( status: 400, body: 'some error' )

    post :callback_submit

    expect(response.body).to eq({error: 'some error'}.to_json)
  end

现在的问题是rspec输出是:

   expected: "{\"error\":\"some error\"}"
        got: "{\"error\":\"\"}"

奇怪的是,我可以将控制器更改为puts一些细节......

  rescue RestClient::BadRequest => e
    error = e.response.body.to_s
    puts error.class
    puts error
    render status: :bad_request, json: { error: error }

哪个输出:

String
some error

   expected: "{\"error\":\"some error\"}"
        got: "{\"error\":\"\"}"

所以error变量似乎是一个字符串和正确的值,但是render将它变成一个空字符串。

现在它变得非常奇怪......如果我插入字符串:

  rescue RestClient::BadRequest => e
    error = e.response.body.to_s
    puts error.class
    puts error
    render status: :bad_request, json: { error: "#{error}" }

或者只是简单地说:

  rescue RestClient::BadRequest => e
    render status: :bad_request, json: { error: "#{e.response.body}" }

然后我的测试通过了!

起初我以为e.response.body不能是字符串,这就是为什么我putsclass打印“字符串”并在其上调用.to_s,但是这似乎没有任何改变。

任何人都可以解释这种奇怪的行为吗?

2 个答案:

答案 0 :(得分:3)

问了一些Ruby朋友,其中一个发现了问题,但是不想在这里发布答案....

问题最终导致我们处于较早的RestClient(1.8)。 In the RestClient 2.0 notes

  

响应对象现在是String的子类,而不是混合在响应功能中的String。

     

Response#body和#to_s现在将返回一个真正的String对象而不是self。以前没有简单的方法来获取真正的String响应,而不是混合了AbstractResponse的Frankenstein响应字符串对象。

所以在我使用的旧版本中,e.response最终成为了这个奇怪的String mixin mashup,render似乎不喜欢它。

插值再次将其转换为真正的Ruby字符串。

答案 1 :(得分:0)

问题是response.body正在查看响应对象,并且由于错误,正文为空。

您可能需要e.message或仅e.to_s这将是错误消息(或错误类名称)而不是响应正文。

摘录:

class Exception < RuntimeError
  attr_accessor :response
  attr_writer :message
  #.......
  def to_s
    message
  end

  def message
    @message || default_message
  end

  def default_message
    self.class.name
  end
end

Source

相关问题