2009-07-22 20 views
32

¿Hay alguna manera de trozar Kernel.sleep en un escenario rspec?RSpec: stubbing Kernel :: sleep?

+0

¿Está buscando algo más allá Kernel :: stubs (: sleep) –

+0

Me imagino que querría que funcionara y no durmiera, tal vez ralentizando su prueba ... – Rich

Respuesta

43

Si llama dentro de la contexto de un objeto, se debe stub en el objeto, así:

class Foo 
    def self.some_method 
    sleep 5 
    end 
end 

it "should call sleep" do 
    Foo.stub!(:sleep) 
    Foo.should_receive(:sleep).with(5) 
    Foo.some_method 
end 

la clave es, a stub en el sueño lo que sea "yo" se encuentra en el contexto donde se llama sueño.

+1

¡Funcionó muy bien para mí, aplausos! – opsb

+0

Trozar el objeto bajo prueba no es una buena idea. Por ejemplo, ver: http://robots.thoughtbot.com/don-t-stub-the-system-under-test – georgebrock

+1

@georgebrock por razones irrelevantes, ¿no? Creo que [esto] (http://stackoverflow.com/a/27749263/52499) es la forma que mejor transmite la intención. Y debe estar usando una sintaxis más nueva. 'allow_any_instance_of (Object) .to receive (: sleep)' –

2

Si está utilizando Mocha, entonces algo como esto funcionará:

def setup 
    Kernel.stubs(:sleep) 
end 

def test_my_sleepy_method 
    my_object.take_cat_nap! 
    Kernel.assert_received(:sleep).with(1800) #should take a half-hour paower-nap 
end 

O si está usando rr:

def setup 
    stub(Kernel).sleep 
end 

def test_my_sleepy_method 
    my_object.take_cat_nap! 
    assert_received(Kernel) { |k| k.sleep(1800) } 
end 

Usted probablemente no debe ser más pruebas problemas complejos de enhebrado con pruebas unitarias. Sin embargo, en las pruebas de integración, utilice el Kernel.sleep real, que lo ayudará a descubrir problemas complejos de enhebrado.

4

En pura rspec:

before do 
    Kernel.stub!(:sleep) 
end 

it "should sleep" do 
    Kernel.should_receive(:sleep).with(100) 
    Object.method_to_test #We need to call our method to see that it is called 
end 
+8

Para aclarar, porque esto no funcionó para mí de inmediato, debe llamar a Kernel .sleep, para burlarse de esta manera. Simplemente llamando a sleep directamente falla –

+0

Sí, el método al que llame tendrá esa suspensión en él. – nitecoder

0

Necesitaba código auxiliar requiere y después de buscar mucho me encontré con que la única manera que trabajó para mí es este sueño

def method_using_sleep 
    sleep 
    sleep 0.01 
end 

it "should use sleep" do 
    @expectations = mock('expectations') 
    @expectations.should_receive(:sleep).ordered.with() 
    @expectations.should_receive(:sleep).ordered.with(0.01) 

    def sleep(*args) 
    @expectations.sleep(*args) 
    end 

    method_using_sleep 
end 
0

No pude obtener las otras soluciones aquí para que funcionen. Tal vez algo ha cambiado en la forma en que se maneja el sueño en las versiones más nuevas de Ruby, o alguna otra cosa.

Lo que terminé haciendo fue poner mono-parche en la clase Objeto, ya que parece que esto es lo que recibe las llamadas de espera. Así que simplemente agregué esto:

class Object 
    def sleep(*args) 
    end 
end 

Así que el método de dormir ahora no hace nada en lugar de algo. Puede haber alguna forma de burlarse de esto mejor, pero no pude encontrar una buena solución sin burlarme del sleep metohd de cada objeto que potencialmente lo usaba.

+0

Consulte mi solución a continuación. rspec-mock está aquí, así que no tienes que parchear – Benj

11

Cuando la llamada a sleep no está dentro de un objeto (mientras se prueba una tarea rake por ejemplo), se puede añadir lo siguiente en una antes del bloque (3 sintaxis rspec)

allow_any_instance_of(Object).to receive(:sleep)