ruby on rails - tests - ¿El método RSpec stubbed puede devolver diferentes valores en secuencia?
rspec rails 5 (4)
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 como:
@family.stub(:location) { rand.to_s }
Tengo una familia modelo con una location
método que fusiona los resultados de location
de otros objetos, Miembros. (Los miembros están asociados con familias, pero eso no es importante aquí).
Por ejemplo, dado
- member_1 tiene una
location
== ''San Diego (viajando, regresa el 15 de mayo)'' - member_2 tiene
location
== ''San Diego''
Family.location puede devolver ''San Diego (member_1 viajando, regresa 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 diferentes valores en una secuencia estaría bien. ¿Hay alguna manera de hacer esto en RSpec?
Es posible anular el método Member.location 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 anulación "envenena" los ejemplos posteriores.
Entonces, ¿hay alguna manera de que un método anulado devuelva valores diferentes y especificados en cada llamada?
Puede resguardar un método para devolver diferentes valores cada vez que se invoca;
allow(@family).to receive(:location).and_return(''first'', ''second'', ''other'')
Por lo tanto, la primera vez que llame a @family.location
devolverá ''first'', la segunda vez devolverá ''second'' y todas las veces que lo llame devolverá ''other''.
Si por alguna razón quieres usar la sintaxis anterior, aún puedes:
@family.stub(:location).and_return(''foo'', ''bar'')
Sintaxis de RSpec 3:
allow(@family).to receive(:location).and_return("abcdefg", "bcdefgh")