2008-11-25 14 views

Respuesta

22

Here's the commit which adds the feature to rspec - este fue el 25 de mayo de 2008. Con esto se puede hacer

A.any_instance.stub(do_something: 23) 

Sin embargo, la última joya v La ersión de rspec (1.1.11, octubre de 2008) no tiene este parche.

This ticket indica que lo arrancaron por motivos de mantenimiento y aún no se ha proporcionado una solución alternativa.

Parece que no puede hacerlo en este momento. Tendrás que hackear la clase manualmente usando alias_method o somesuch.

+3

parece que se ha sido traído de vuelta con 2.6.0 por lo que está allí ahora ... – rogerdpack

+3

@rogerdpack: de hecho, ¡por fin! http://blog.davidchelimsky.net/2011/05/12/rspec-260-is-released/ "Agregar compatibilidad para any_instance.stub y any_instance.should_receive" – tokland

+0

Cualquier idea si desea adjuntar algo directamente a esa instancia creada por nuevo, sin embargo? como should_receive (: blah) .exactlY (5) .times --- y no quieres eso para ningún objeto, solo ese específicamente? – xaxxon

11

No sé cómo hacer eso en el marco simulacro de especificación, pero se puede cambiar fácilmente hacia fuera para moka para hacer 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 
5

o con RR:

stub.any_instance_of(A).do_something { 23 } 
-1

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

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

Sé que es probable que sea demasiado tarde para responder a su creador original, pero me contesto que de todos modos para futura referencia, ya Vine aquí con la misma pregunta pero descubrí que estaba trabajando en la última versión de rspec.

+0

El comportamiento de su sugerencia es incorrecto. Es el método: do_something que devuelve 42, no el inicializador. –

0

Para stub 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 pschneider señaló, acabo de volver de nuevo con 42: A.stub(:new).and_return(42) o algo por el estilo.

+0

Creo que el objetivo es resguardar el método de instancia cuando no tienes el control de crear instancias en tu prueba. Además, el inicializador no devuelve 42, sino que establece una variable de instancia: es el método do_something que devuelve 42 que debe ser anulado. –

+1

El 'A.stub (: new) .and_return (@my_stub)' devolverá el resguardo de instancia cada vez, lo que le da control sobre la creación de la instancia. En cuanto a la configuración de la variable miembro, siempre he oído que no se debe preocupar por las internas en burlarse/tropezar, solo interfaces públicas. Por lo tanto, solo devuelva los valores correctos para el método que depende de '@ x'. Probablemente estoy equivocado – bluehavana

16

he encontrado 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 
2

hago como respuesta Denis Barushev. Y me gustaría sugerir un solo cambio cosmético que hace que la variable new_method sea innecesaria. Rspec hace munge en métodos tropezados, de modo que se puede acceder con proxied_by_rspec__ prefijo:


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

Esta es una muy buena idea, pero no funciona con la versión de RSpec que estoy usando. La respuesta de Denis funciona. – emk

+0

Gracias! Sí, es muy dependiente de la convención de prefijo de nombre "proxied_by_rspec__" que puede no ser parte de la API publicada. Ah, y ".call" no es necesario en la segunda línea, lo siento. Por cierto, ¿qué versión de RSpec estás usando? –

0

Aquí es una idea que podría no ser muy elegante, pero es básicamente seguro para trabajar:

Crear una clase pequeña que hereda la clase que desea probar, sustituir el método de inicialización y llame superdespués de haber creado los talones en la inicialización, así:

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

y yo ¡vete! Acabo de usar esto con éxito en una de mis pruebas.

0

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

2

En RSpec 2.6 o posterior puede utilizar

A.any_instance.stub(do_something: 23) 

Ver the docs para más detalles. (Gracias a rogerdpack para señalar que esto es ahora posible - pensé que merecía una respuesta de su propia)

3

En la última versión del RSpec a partir de hoy - 3.5 se puede:

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