RSpec 和 Open-URI 如何模拟引发 SocketError/TimeoutError

发布于 2024-07-13 20:47:15 字数 691 浏览 5 评论 0原文

我希望能够指定当 Open-Uri open() 调用超时或引发异常(例如 SocketError)时,我正在按预期处理事情,但是我遇到了麻烦。

这是我的规范(针对 SocketError):

@obj.should_receive(:open).with("some_url").and_raise(SocketError)

以及我使用 open-uri 的对象部分:

begin
  resp = open(url)
  resp = resp.read
rescue SocketError
  something = true
end

但是在这种情况下,规范会失败,并出现 nil.read 错误。

这是本周我第二次遇到这个问题,上一次我试图在用 timeout() {}open() 时模拟 TimeoutError >,那一次我放弃了,只是通过开放课程导致了实际的超时。 我显然可以通过尝试调用无效的 URL 来引发 SocketError,但我确信有一种正确的方法可以使用 RSpec 来模拟它。

更新:我显然没有在深夜思考清楚,错误实际上是当我在 SocketError 之后重新尝试 URL 时, and_raise(SocketError) 部分工作正常。

I want to be able to spec out that when Open-Uri open() calls either timeout or raise an exception such as SocketError I am handling things as expected, however I'm having trouble with this.

Here is my spec (for SocketError):

@obj.should_receive(:open).with("some_url").and_raise(SocketError)

And the part of my object where I'm using open-uri:

begin
  resp = open(url)
  resp = resp.read
rescue SocketError
  something = true
end

However in this situation the spec fails as with a nil.read error.

This is the second time this week I've come across this problem, the previous time I was attempting to simulate a TimeoutError when wrapping open() with a timeout() {}, that time I gave up and just caused an actual timeout to happen by opening up the class. I could obviously cause this to throw a SocketError by trying to call an invalid URL, but I'm sure there is a correct way to mock this out with RSpec.

Update: I obviously wasn't thinking clearly that late at night, the error was actually when I re-tried the URL after the SocketError, the and_raise(SocketError) part worked fine.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清风疏影 2024-07-20 20:47:15

根据您提供的信息,您提供的行应该可以工作:我制作了一个小型测试类和规范(见下文),仅包含所描述的功能,并且事情的行为符合预期。 如果您可以提供更多上下文,这可能会有所帮助 - 例如,规范中的完整“it”块可能会暴露一些其他问题。

如前所述,以下规范通过了,我相信它捕获了您试图验证的逻辑:

require 'rubygems'
require 'spec'

class Foo
  attr_accessor :socket_error

  def get(url)
    @socket_error = false
    begin
      resp = open(url)
      resp = resp.read
    rescue SocketError
      @socket_error = true
    end
  end
end

describe Foo do
  before do
    @foo = Foo.new
  end

  it "should handle socket errors" do
    @foo.should_receive(:open).with("http://www.google.com").and_raise(SocketError)
    @foo.get("http://www.google.com")
    @foo.socket_error.should be_true
  end
end

The line you provided should work, based on the information you've given: I made a tiny test class and spec (see below) with only the described functionality, and things behaved as expected. It might be helpful if you could provide a little more context - the full "it" block from the spec, for instance, might expose some other problem.

As mentioned, the following spec passes, and I believe it captures the logic you were attempting to verify:

require 'rubygems'
require 'spec'

class Foo
  attr_accessor :socket_error

  def get(url)
    @socket_error = false
    begin
      resp = open(url)
      resp = resp.read
    rescue SocketError
      @socket_error = true
    end
  end
end

describe Foo do
  before do
    @foo = Foo.new
  end

  it "should handle socket errors" do
    @foo.should_receive(:open).with("http://www.google.com").and_raise(SocketError)
    @foo.get("http://www.google.com")
    @foo.socket_error.should be_true
  end
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文