2011-05-10 8 views
50

Tengo un modelo Familia con un método location que combina las salidas location de otros objetos, Miembros. (Los miembros están asociados con las familias, pero eso no es importante en este caso.)¿Puede el método resuelto RSpec devolver diferentes valores en secuencia?

Por ejemplo, dada

  • member_1 ha location == 'San Diego (itinerante, devuelve 15 de mayo)'
  • member_2 tiene location == 'San Diego'

Family.location podría devolver 'San Diego (member_1 viajando, devoluciones 15 de mayo)' Los detalles no son importantes.

Para simplificar las pruebas de Family.location, quiero resguardar Member.location. 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 reemplazar el método Member.location dentro de cada ejemplo de ensayo, tales 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 esto es 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 anulación "envenena" los ejemplos posteriores.

Entonces, ¿hay alguna manera de que un método troquelado devuelva diferentes valores especificados en cada llamada?

Respuesta

108

Puede encontrar un método para devolver diferentes valores cada vez que se invoca;

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

Así que la primera vez que llame @family.location volverá 'primero', la segunda vez que volverá 'segunda', y todos los tiempos posteriores se llame, se volverá 'otro'.

+0

Gracias por la consejo – apneadiving

+0

¡Gracias, idlefingers! –

+0

Gracias @idlefingers! ¿Qué pasa si quieres devolver una gran cantidad de valores? –

0

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

Algo así como:

@family.stub(:location) { rand.to_s } 
12

RSpec 3 sintaxis:

allow(@family).to receive(:location).and_return("abcdefg", "bcdefgh") 
0

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

@family.stub(:location).and_return('foo', 'bar') 
Cuestiones relacionadas