2011-03-27 9 views
7

¿Es de alguna manera posible probar las advertencias i Ruby usando RSpec?Prueba de advertencias usando RSpec

De esta manera:

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

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

Respuesta

15

warn se define en Kernel, que se incluye en cada objeto. Si usted no estaba criando la advertencia durante la inicialización, se puede especificar una advertencia como esta:

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

spec'ing una advertencia planteado en el método initialize es bastante más compleja. Si es necesario, puede intercambiar un objeto falso IO por $stderr e inspeccionarlo. Sólo asegúrese de restaurarla siguiendo el ejemplo

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 
+0

podrías hacer '' SomeClass.allocate' en lugar de SomeClass .new', y luego darle el should_receive, y luego ejecutar initialize? –

+0

El otro enfoque que he usado para advertencias en 'initialize' es hacer que mi clase llame' Kernel.warn' explícitamente (en lugar de solo 'warn'). No necesita ser llamado en kernel; solo necesita ser llamado en algunos globales que puedo establecer un 'should_receive' antes de la creación de instancias. –

4

Hay un buen artículo con las expectativas a medida que resuelve exactamente su problema: http://greyblake.com/blog/2012/12/14/custom-expectations-with-rspec/

Por lo tanto, le gustaría:

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

Base en que artículo puede crear su propia expectativa para usarlo así:

+2

Esta es una respuesta increíble, pero recomendaría incluir la mayor parte del artículo en la respuesta en caso de que el artículo no funcione. – sunnyrjuneja

0

Esta es mi solución, que definen un has_warn de coincidencias personalizada

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 

ahora se puede utilizar esta función como sigue en pos de incluir los CustomMatchers:

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