En RSpec, ¿hay un método equivalente a " unstub "pero para"should receive"?


¿Hay algún método para eliminar cualquier stubbing y burlarse mientras se usa RSpec?

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 require).

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

Author: p.matsinopoulos, 2012-06-01

3 answers

Por el momento (rspec-mocks 2.10.1) no hay un método equivalente a unstub sino para should_receive. Puede restablecer todos los stubs y burlas usando rspec_reset, y también puede escribir hacks sucios para eliminar una expectativa en particular (que no recomendaría).

El siguiente es un ejemplo de eliminación de todos los stubs y expectativas en 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 está anotado en el código fuente de rspec como @private, lo que significa que debe evitar usarlo más que absolutamente necesario y puede romperse en futuras versiones de rspec sin previo aviso. Es, sin embargo, bastante ampliamente utilizado en las especificaciones para el propio rspec, por lo que parece menos probable que esto sea obsoleto en el corto plazo.

Después de excavar a través del código rspec-se 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 realmente malo ya que viola la encapsulación del paquete de prueba rspec y no debería hacerlo. En cambio, si realmente tenía una razón convincente para eliminar una expectativa en particular, lo correcto sería agregar un método público ascendente en rspec-mocks que agrega un método paralelo a unstub pero para eliminar expectativas específicas. Probablemente estaría ubicado aquí (note la definición de stub y unstub también en este archivo):

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

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

La única excepción a esto puede ser, por supuesto, en el conjunto de pruebas de rspec-mocks, donde rspec_reset se utiliza para restablecer el estado entre los ejemplos que prueban la funcionalidad de aplicar stubs y simuladores. A menos que esté haciendo eso, lo más probable es que sus pruebas podrían mejorarse para no confiar en reseteos globales de stubs y burlas en un objeto.

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

 29
Author: Justin Leitgeb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-02 17:16:24

Puede sobrescribir algunas burlas anteriores:

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

O si no fuera cualquier tipo de expectativa, solo un simple trozo:

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

Recuerda que también existe expect_any_instance_of y allow_any_instance_of.

 36
Author: Waiting for Dev...,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-27 09:04:54

Para RSpec >= 2.14, la respuesta aceptada ya no funcionará. Te remito a la respuesta de Bernhard Köhler en este hilo (reproducido a continuación para proteger contra la putrefacción de enlaces): método indefinido 'rspec_reset' con rspec versión 2.14

El método reset no existe en RSpec 2.14. En cambio, es un ayudante método definido dentro del spec_helper.archivo rb para el rspec-burlas proyecto.

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

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

Puede ver que este método delega la acción de restablecimiento a la proxy subyacente en lugar de agregarlo a la definición de clase de el objeto en cuestión.

 6
Author: JellicleCat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:02