2010-11-11 28 views
45

Tengo un modelo con un método privado que me gustaría especificar con RSpec,
¿cómo se suele hacer? ¿Solo prueba el método llamando al privado?
o también especifique el privado? si es así, ¿cómo estás?Cómo especificar un método privado

Respuesta

109

Siempre tomo este enfoque: Quiero probar la API pública que expone mi clase.

Si tiene métodos privados, solo los llama desde los métodos públicos que expone a otras clases. Por lo tanto, si prueba que esos métodos públicos funcionan como se espera en todas las condiciones, también ha demostrado que los métodos privados que utilizan funcionan también.

Admitiré que he encontrado algunos métodos privados especialmente complejos. En ese caso extremo que desea probar ellos, se puede hacer esto:

@obj.send(:private_method) 
+1

Gracias por su ayuda, acepto que probar el método público demuestra que el privado también funciona. Dicho esto, realmente quiero probar el método privado y su solución funciona como un encanto. ¡Gracias! – Mike

+2

Aquí hay otro enfoque interesante http://kailuowang.blogspot.com/2010/08/testing-private-methods-in-rspec.html – gucki

+1

Tengo un gancho before_save en mi modelo que guarda un token privado en la base de datos a través de un privado método 'make_private_token'. El método 'make_private_token' utiliza métodos de clase pública, y no al revés, por lo que la única forma en que puedo probarlo es con el método 'send'. No veo nada 'extreme' sobre eso ... – Starkers

6

Para los métodos privados que necesitan cobertura de código (ya sea temporal o permanentemente), utilice el rspec-context-private gem para hacer temporalmente los métodos públicos y privados dentro de un contexto.

gem 'rspec-context-private' 

Funciona al agregar un contexto compartido a su proyecto.

RSpec.shared_context 'private', private: true do 

    before :all do 
    described_class.class_eval do 
     @original_private_instance_methods = private_instance_methods 
     public *@original_private_instance_methods 
    end 
    end 

    after :all do 
    described_class.class_eval do 
     private *@original_private_instance_methods 
    end 
    end 

end 

Entonces, si pasa :private como metadatos a un bloque describe, los métodos privados serán públicos dentro de ese contexto.

class Example 
    private def foo 
    'bar' 
    end 
end 

describe Example, :private do 
    it 'can test private methods' do 
    expect(subject.foo).not eq 'bar' 
    end 
end 
+0

No sé si usted mantiene esta gema más, pero su documentación no tiene el bloque de código sobre la declaración del shared_context. Así que no pude hacer que funcionara simplemente leyendo la documentación. Después de agregar en este bloque, está funcionando como se esperaba. – istrasci

0

Si tienes intención de probar una expectativa en un método privado, la respuesta aceptada realidad no va a trabajar (al menos no que yo sepa, así que estoy abierto a la corrección en ese momento). Lo que he hecho es aún más sucio lugar - en la prueba en sí, sólo exponer el método redefiniéndola:

def object_to_test.my_private_method 
    super 
end 

Obras en Rubí 1.8, no puede hacer comentarios sobre cualquiera de los tiempos de ejecución más recientes.

Cuestiones relacionadas