una tipos que programacion orientada objetos objeto metodos herencia ejemplos constructores clases clase atributos ruby rspec stub

ruby - tipos - que es una clase en programacion



rspec: ¿Cómo resguardar un método de instancia llamado por el constructor? (11)

Encontré esta solución en http://pivotallabs.com/introducing-rr/

new_method = A.method(:new) A.stub!(:new).and_return do |*args| a = new_method.call(*args) a.should_receive(:do_something).and_return(23) a end

class A def initialize @x = do_something end def do_something 42 end end

¿Cómo puedo do_something en rspec antes de llamar a la implementación original (asignando 42 a @x )? Y sin cambiar la implementación, por supuesto.


No sé cómo hacer eso en el marco simulado de las especificaciones, pero puedes cambiarlo fácilmente para que Mocha haga lo siguiente:

# should probably be in spec/spec_helper.rb Spec::Runner.configure do |config| config.mock_with :mocha end describe A, " when initialized" do it "should set x to 42" do A.new.x.should == 42 end end describe A, " when do_something is mocked" do it "should set x to 23" do A.any_instance.expects(:do_something).returns(23) A.new.x.should == 23 end end


o con RR :

stub.any_instance_of(A).do_something { 23 }


En mi versión de rspec (1.2.2) puedo hacer esto:

A.should_receive(:new).and_return(42)

Sé que es demasiado tarde para responder al póster original, pero lo respondo de todos modos para futuras referencias, ya que vine aquí con la misma pregunta pero descubro que estaba trabajando en la última versión de rspec.


Para resguardar un método de instancia, puede hacer algo como esto:

before :each do @my_stub = stub("A") @my_stub.should_receive(:do_something).with(no_args()).and_return(42) @my_stub.should_receive(:do_something_else).with(any_args()).and_return(true) A.stub(:new).and_return(my_stub) end

Pero como señaló pschneider, simplemente devuelve 42 en new con: A.stub(:new).and_return(42) o algo por el estilo.


Me gusta la respuesta de Denis Barushev. Y me gustaría sugerir un solo cambio cosmético que hace que la variable new_method sea ​​innecesaria. Rspec aplica métodos trozados, de modo que se puede acceder con el prefijo proxied_by_rspec__ :

A.stub!(:new).and_return do |*args| a = A.proxied_by_rspec__new(*args) a.should_receive(:do_something).and_return(23) a end


Aquí hay una idea que puede no ser muy elegante, pero que básicamente funciona:

Cree una pequeña clase que herede la clase que desea probar, anule el método de inicialización y llame a super después de haber creado los apéndices en la inicialización, de esta forma:

it "should call during_init in initialize" do class TestClass < TheClassToTest def initialize should_receive(:during_init) super end end TestClass.new end

Y ahí tienes! Acabo de usar esto con éxito en una de mis pruebas.


La gema rspec_candy viene con un método de ayuda stub_any_instance que funciona tanto en RSpec 1 como en RSpec 2.


Aquí está la confirmación que agrega la característica a rspec - Esto fue el 25 de mayo de 2008. Con esto puedes hacer

A.any_instance.stub(do_something: 23)

Sin embargo, la última versión de gema de rspec (1.1.11, octubre de 2008) no tiene este parche.

Este boleto indica que lo sacaron por razones de mantenimiento y aún no se ha proporcionado una solución alternativa.

No parece que puedas hacerlo en este punto. Tendrás que hackear la clase manualmente usando alias_method o somesuch.


En la última versión de RSpec a partir de hoy - 3.5 puedes:

allow_any_instance_of(Widget).to receive(:name).and_return("Wibble")


En RSpec 2.6 o posterior, puedes usar

A.any_instance.stub(do_something: 23)

Ver los documentos para más detalles. (Gracias a rogerdpack por señalar que esto ahora es posible, pensé que merecía una respuesta propia)