使用RSpec测试警告

时间:2011-03-27 12:24:26

标签: ruby testing rspec warnings

在某种程度上可以使用RSpec测试Ruby的警告吗?

像这样:

class MyClass
  def initialize
    warn "Something is wrong"
  end
end

it "should warn" do
  MyClass.new.should warn("Something is wrong")
end

3 个答案:

答案 0 :(得分:16)

warnKernel中定义,包含在每个对象中。如果您在初始化期间没有提出警告,则可以指定如下警告:

obj = SomeClass.new
obj.should_receive(:warn).with("Some Message")
obj.method_that_warns

initialize方法中引发警告要复杂得多。如果必须这样做,您可以交换假IO对象$stderr并检查它。请务必在示例

之后恢复它
class MyClass
  def initialize
    warn "Something is wrong"
  end
end

describe MyClass do
  before do
    @orig_stderr = $stderr
    $stderr = StringIO.new
  end

  it "warns on initialization" do
    MyClass.new
    $stderr.rewind
    $stderr.string.chomp.should eq("Something is wrong")
  end

  after do
    $stderr = @orig_stderr
  end
end

答案 1 :(得分:6)

有一篇关于自定义期望的好文章可以解决您的问题:http://greyblake.com/blog/2012/12/14/custom-expectations-with-rspec/

所以它想:

expect { MyClass.new }.to write("Something is wrong").to(:error)

根据那篇文章,你可以创建自己的期望,就像这样使用它:

expect { MyClass.new }.to warn("Something is wrong")

答案 2 :(得分:-1)

这是我的解决方案,我定义了一个自定义匹配器has_warn

require 'rspec'
require 'stringio'

module CustomMatchers
  class HasWarn
    def initialize(expected)
      @expected = expected
    end

    def matches?(given_proc)
      original_stderr = $stderr
      $stderr = StringIO.new
      given_proc.call
      @buffer = $stderr.string.strip
      @expected.include? @buffer.strip
    ensure
      $stderr = original_stderr
    end

    def supports_block_expectations?
      true
    end

    def failure_message_generator(to)
      %Q[expected #{to} get message:\n#{@expected.inspect}\nbut got:\n#{@buffer.inspect}]
    end

    def failure_message
      failure_message_generator 'to'
    end

    def failure_message_when_negated
      failure_message_generator 'not to'
    end

  end

  def has_warn(msg)
    HasWarn.new(msg)
  end
end

现在,您可以在包含CustomMatchers后使用此功能:

expect{ MyClass.new }.to has_warn("warning messages")