Is it somehow possible to test warnings i Ruby using RSpec?
Like this:
class MyClass
def initialize
warn \"Something is wrong\"
end
end
it \
There is a good article with custom expectation which solves exactly your problem: http://greyblake.com/blog/2012/12/14/custom-expectations-with-rspec/
So it would like:
expect { MyClass.new }.to write("Something is wrong").to(:error)
Base on that article you can create you own expectation to use it like this:
expect { MyClass.new }.to warn("Something is wrong")
This is my solution, I define a custom matcher 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
now you can use this function as follow after include the CustomMatchers:
expect{ MyClass.new }.to has_warn("warning messages")
warn
is defined in Kernel
, which is included in every object. If you weren't raising the warning during initialization, you could specify a warning like this:
obj = SomeClass.new
obj.should_receive(:warn).with("Some Message")
obj.method_that_warns
Spec'ing a warning raised in the initialize
method is quite more complex. If it must be done, you can swap in a fake IO
object for $stderr
and inspect it. Just be sure to restore it after the example
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