【问题标题】:Rspec should_receive and abortRspec should_receive 和 abort
【发布时间】:2014-02-11 17:27:39
【问题描述】:

我有以下代码:

class Init
  def initialize(global_options, options, args)
    abort "Key file must be given!" if (key_file = args.first).nil?

    begin
      @secret = File.read(key_file)
    rescue
      abort "Cannot read key file #{key_file}"
    end

    stdout, stderr, status = Open3.capture3("git status  -uno --porcelain")
    #...

以及以下规格:

describe Rgc::Init do
  context :initialize do
    it 'should abort when no key file given' do
      Rgc::Init.any_instance.should_receive(:abort)
        .with("Key file must be given!")

      Rgc::Init.new({}, {}, [])
    end
  end
end

我得到以下输出:

Failure/Error: Rgc::Init.new({}, {}, [])
#<Rgc::Init:0x0000000157f728> received :abort with unexpected arguments
expected: ("Key file must be given!")
got: ("Cannot read key file ")

should_receive 方法以某种方式阻止 abort 占位。如何修复规范以检查应用程序是否已中止并带有特定消息?

【问题讨论】:

    标签: ruby rspec rspec2


    【解决方案1】:

    您的两个期望需要被视为不同的事物。首先,正如您所注意到的,abort 现在已被存根,因此实际上并没有中止您的代码的执行——它实际上就像现在的 puts 语句一样。因此, abort 被调用了两次:一次是您的预期消息,然后是您的 begin 块内。如果您在期望的末尾添加{ abort },它实际上会中止,但这也会中止您的测试套件。

    你应该做的是使用 lambda 并确保 abort 被调用:

    lambda { Rgc::Init.new({}, {}, []) }.should raise_error SystemExit
    

    abort 将您提供给 stderr 的消息打印出来。为了捕捉到这一点,您可以添加一个帮助器,用 StringIO 对象临时替换 stderr,然后您可以检查以下内容:

    def capture_stderr(&block)
      original_stderr = $stderr
      $stderr = fake = StringIO.new
      begin
        yield
      ensure
        $stderr = original_stderr
      end
      fake.string
    end
    
    it 'should abort when no key file given' do
      stderr = capture_stderr do
        lambda { Rgc::Init.new({}, {}, []) }.should raise_error SystemExit
      end
      stderr.should == "Key file must be given!\n"
    end
    

    (感谢https://stackoverflow.com/a/11349621/424300 替换stderr)

    【讨论】:

    • 尽管这就是我编写测试的方式(为此目的赞成),但它仍然不能解释为什么 OP 在STDOUTSTDERR 中收到不同的消息。可能是
    • @bjhaid 他得到它是因为他已经存根 abort,因此 abort 的实际功能(以 SystemExit 退出)不会发生,所以他的代码继续到 @987654336 @块。
    • @bjhaid 我在回答中添加了一些说明。
    • @DylanMarkow 我认为这是您应该使用的答案:relishapp.com/rspec/rspec-expectations/v/2-6/docs/… 这与预期的异常和消息匹配,但不指向 stderr 或 stdout
    • 很好的答案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-16
    • 1970-01-01
    • 2012-06-09
    相关资源
    最近更新 更多