使用RSpec测试警告

是否有可能使用RSpec测试Ruby的警告?

像这样:

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

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

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

initialize方法中引发警告是非常复杂的。 如果必须这样做,您可以为$stderr交换一个伪IO对象并检查它。 请务必在示例后恢复它

 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 

有一篇关于自定义期望的好文章可以解决您的问题: 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") 

这是我的解决方案,我定义了一个自定义匹配器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后使用此function:

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