¿Puede el método RSpec stubbed devolver diferentes valores en secuencia?


Tengo una Familia de modelos con un método location que fusiona las salidas location de otros objetos, Miembros. (Los miembros están asociados con familias, pero eso no es importante aquí.)

Por ejemplo, dado

  • member_1 has location = = 'San Diego (traveling, returns 15 May)'
  • member_2 has location = = 'San Diego'

Familia.location might return 'San Diego (member_1 traveling, returns 15 May)' Los detalles no son importantes.

Para simplificar la pruebas de Familia.ubicación, quiero un miembro de stub.ubicación. Sin embargo, necesito que devuelva dos valores diferentes (especificados) como en el ejemplo anterior. Idealmente, estos se basarían en un atributo de member, pero simplemente devolver valores diferentes en una secuencia estaría bien. ¿Hay alguna manera de hacer esto en RSpec?

Es posible anular el Miembro.método de ubicación dentro de cada ejemplo de prueba, como

it "when residence is the same" do 
  class Member
    def location
      return {:residence=>'Home', :work=>'his_work'} if self.male?
      return {:residence=>'Home', :work=>'her_work'}
    end
  end
  @family.location[:residence].should == 'Home'
end

Pero dudo que esta sea una buena práctica. En cualquier caso, cuando RSpec está ejecutando una serie de ejemplos no restaura la clase original, por lo que este tipo de sobrescribir "envenena" los ejemplos posteriores.

Entonces, ¿hay una manera de que un método stubbed devuelva valores diferentes y especificados en cada llamada?

Author: Mike Blyth, 2011-05-10

4 answers

Puede stub un método para devolver diferentes valores cada vez que se llama;

allow(@family).to receive(:location).and_return('first', 'second', 'other')

Así que la primera vez que llames a @family.location devolverá 'primero', la segunda vez devolverá 'segundo', y todas las siguientes veces que lo llames, devolverá 'otro'.

 118
Author: idlefingers,
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-05-01 08:47:48

RSpec 3 sintaxis:

allow(@family).to receive(:location).and_return("abcdefg", "bcdefgh")
 12
Author: nothing-special-here,
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
2014-09-10 15:12:27

Si por alguna razón desea utilizar la sintaxis antigua, todavía puede:

@family.stub(:location).and_return('foo', 'bar')
 0
Author: ndn,
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-01-23 15:16:38

He intentado el esquema de la solución aquí arriba, pero no funciona para mi. Resolví el problema stubbing con una implementación sustituta.

Algo como:

@family.stub(:location) { rand.to_s }
 0
Author: matteo,
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-10-31 20:42:45