2012-06-01 8 views
32

¿Hay algún método para eliminar cualquier trozo y burla mientras se usa RSpec?En RSpec, ¿hay un método equivalente a "unstub" pero para "should_receive"?

Ejemplo:

RestClient.should_receive(:delete).with("http://www.example.com") 
... 
... 

# this will remove the mocking of "should_receive" and 
# restore the proper "delete" method on "RestClient". 
RestClient.mocking_reset 

(mocking_reset es mi nombre ficticio para la funcionalidad requerir).

Sé que existe el método "unstub" que restablece "stubs" pero no "should_receive" s.

Entonces, ¿hay algún método equivalente a "unstub" pero para "should_receive"?

Panayotis

+0

¡Es ridículo que no puedas hacer una edición de menos de 6 caracteres! Su nombre de método dice 'mocking_resest' y debería decir' mocking_reset'. –

+0

Agregue un mensaje de edición y su edición excederá los 6 caracteres :) – Galen

Respuesta

29

En el momento (rspec-burla 2.10.1) no es un método equivalente a unstub pero para should_receive. Puede restablecer todos los resquicios y burlas con rspec_reset, y también puede escribir hacks sucios para eliminar una expectativa particular (que no recomendaría).

El siguiente es un ejemplo de la eliminación de todos los talones y las expectativas sobre un objeto:

describe "resetting stubs and expectations with rspec_reset" do 
    before do 
    @person = mock('person') 
    @person.should_receive(:poke) 
    end 

    it "should not fail when we reset all stubs and expectations" do 
    @person.rspec_reset 
    end 
end 

Tenga en cuenta que este método se anota en el código fuente rspec como @private, lo que significa que usted debe evitar el uso de más de lo absolutamente necesario y puede romperse en versiones futuras de rspec sin previo aviso. Sin embargo, es ampliamente utilizado en las especificaciones de rspec en sí, por lo que parece menos probable que esto se desaproveche pronto.

Después de cavar a través del código rspec-burla un poco más, por supuesto puede hacer algo realmente desagradable y arrancar la expectativa específica usted mismo:

# Works in rspec 2.10.1 
describe "removing an expectation with an ugly hack" do 
    before do 
    @person = mock('person') 
    @person.should_receive(:poke) 
    end 

    it "should not fail after we hack rspec by violating every law of good programming, ever" do 
    @person.instance_variable_get(:@mock_proxy).instance_variable_get(:@method_double)[:poke].clear 
    end 
end 

Esto es muy malo ya que viola la encapsulación de el paquete de prueba rspec y no deberías hacerlo. En cambio, si realmente tiene una razón convincente para eliminar una expectativa particular, lo correcto sería agregar un método público en sentido ascendente en rspec-mocks que agregue un método paralelo al unstub pero para eliminar expectativas específicas. Probablemente se encuentra aquí (nota de la definición de stub y unstub así en este archivo):

https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/methods.rb

Antes de salir y el uso de cualquiera de las sugerencias anteriores para eliminar la expectativa es posible que desee considerar si sus especificaciones realmente necesitan hacer esto o si deberían ser refactorizadas. Usar should_receive es una afirmación sobre su código, y generalmente debería intentar crear ejemplos (es decir, bloques it) que solo afirman una cosa. Me gustaría saber por qué necesita algo como rspec_reset a menos que intente hacer demasiado en la configuración global (por ejemplo, before :each o antes: todos los bloques) o si sus ejemplos intentan hacer demasiado (es decir, con múltiples aserciones en un solo ejemplo).

La única excepción a esto puede estar, por supuesto, en el conjunto de pruebas de rspec-mocks, donde rspec_reset se usa para restablecer el estado entre ejemplos que prueban la funcionalidad de la aplicación de stubs y mocks. A menos que esté haciendo eso, es probable que sus pruebas se puedan mejorar para no depender de reinicios globales de trozos y burlas en un objeto.

Espero que esto ayude y hágamelo saber si cree que hay un caso legítimo para agregar un método equivalente al unstub pero para las expectativas del mensaje (es decir, después de usar should_receive). Si estoy convencido de que esto está bien, consideraría agregar este método y proponerlo para ser agregado en sentido ascendente. ¿Tal vez se llamaría unset_expectation? Siéntase libre de usar la guía en el código y las estructuras internas anteriores para armar una solicitud de extracción de rspec-mocks por su cuenta, y veremos si se acepta para crear una burla equivalente al unstub.

+1

Muchas gracias por su respuesta. La razón por la que quería esta funcionalidad era porque tenía un método "clean_test_data" ejecutado "after: each". Esto requería usar los métodos reales. Después de publicar mi pregunta en SOF, me di cuenta de que aún podía usar "clean_test_data" pero en "before: each" y esa era la solución a mi problema. De esa forma, finalmente no necesité unstub ni unmock. Mientras tanto, como he encontrado buenas razones en el pasado para usar "unstub", entonces no veo por qué no tener la "expectativa no establecida" equivalente por razones de exhaustividad y luego dejo que el usuario simulado decida. –

6

Para RSpec> = 2.14, la respuesta aceptada ya no funcionará. Los remito a la respuesta de Bernhard Köhler en este hilo (se reproduce a continuación para protegerse de enlace roto): undefined method `rspec_reset' with rspec version 2.14

El método de reinicio no existe en RSpec 2.14. En su lugar, es un método de ayuda definido dentro del archivo spec_helper.rb para el proyecto rspec-mocks .

module VerifyAndResetHelpers 
    def verify(object) 
    RSpec::Mocks.proxy_for(object).verify 
    end 

    def reset(object) 
    RSpec::Mocks.proxy_for(object).reset 
    end 
end 

Se puede ver que este método delegados la acción de restablecimiento a la representación subyacente en lugar de virar en la definición de la clase de el objeto en cuestión.

31

puede sobrescribir algunos de burla anterior por:

expect(RestClient).to receive(:delete).and_call_original 

O si es que no había ningún tipo de expectativa, simplemente un talón simple:

allow(RestClient).to receive(:delete).and_call_original 

Recuerde existe también expect_any_instance_of y allow_any_instance_of.

Cuestiones relacionadas