2010-09-01 10 views
7

Me gustaría probar que un método se llama recursivamente con un argumento específico.Rspec: cómo probar la recursión?

Mi enfoque:

class Recursable 
    def rec(arg) 
    rec(7) unless arg == 7 
    end 
end 

describe Recursable do 
    it "should recurse" do 
    r = Recursable.new('test') 
    r.should_receive(:rec).with(0).ordered 
    r.should_receive(:rec).with(7).ordered 
    r.rec(0) 
    end 
end 

Inesperadamente, RSpec falla con:

expected :rec with (7) once, but received it 0 times 

Alguna idea de lo que está mal con mi enfoque? ¿Cómo probar la recursión efectiva con un argumento específico?

Respuesta

10

El problema con su prueba tal como está ahora es que está borrando el método que está tratando de probar. r.should_receive(:rec) está reemplazando r#rec con un stub, que por supuesto nunca llama al r.rec(7).

Un mejor enfoque sería simplemente probar que el resultado de la llamada al método inicial es correcto. No debería importar estrictamente si el método recuenta, itera o telefonea a un amigo, siempre y cuando dé la respuesta correcta al final.

+0

Ah, está bien. ¡Oh bien! Estoy tratando de encontrar un error: el método devuelve un valor incorrecto (es más complicado que el que se muestra aquí). Pensé que podría probar cada parte para reducir el espacio problemático. Se vuelve más complicado con cada nivel de recursión y hubiera sido bueno probar si la recursión se ejecuta correctamente. – crispy

+2

En otras palabras: no pruebe la implementación, pruebe el efecto que tiene el código. ¡Gran respuesta! – awendt

2

A menudo, si necesita probar la recursividad, es un olor a código; probablemente debas dividir el método en diferentes responsabilidades o algo.

Pero algunas veces solo necesita agregar algunas verificaciones básicas en su recursión. Puede hacerlo con Rspec and_call_original:

it "should recurse" do 
    r = Recursable.new('test') 
    r.should_receive(:rec).with(0).ordered.and_call_original 
    r.should_receive(:rec).with(7).ordered.and_call_original 
    r.rec(0) 
end 

Normalmente should_receive se acaba de código auxiliar del método real, es por eso que la recursividad no funciona. Con and_call_original, el método stubbed (que contiene las comprobaciones de prueba) también llamará a la implementación del método original, que realizará la recursión como se esperaba.

Cuestiones relacionadas