tutorial tests test run rails que mock how ruby-on-rails testing rspec stub

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")