ruby on rails - Cómo decir "any_instance" "should_receive" cualquier cantidad de veces en RSpec
ruby-on-rails testing (6)
Tengo un controlador de importación en rieles que importa varios archivos csv con múltiples registros en mi base de datos. Me gustaría probar en RSpec si los registros se guardan realmente mediante el uso de RSpec:
<Model>.any_instance.should_receive(:save).at_least(:once)
Sin embargo, recibo el error diciendo:
The message ''save'' was received by <model instance> but has already been received by <another model instance>
Un ejemplo artificial del controlador:
rows = CSV.parse(uploaded_file.tempfile, col_sep: "|")
ActiveRecord::Base.transaction do
rows.each do |row|
mutation = Mutation.new
row.each_with_index do |value, index|
Mutation.send("#{attribute_order[index]}=", value)
end
mutation.save
end
¿Es posible probar esto usando RSpec o hay alguna solución alternativa?
Aquí hay una mejor respuesta que evita tener que anular el: nuevo método:
save_count = 0
<Model>.any_instance.stub(:save) do |arg|
# The evaluation context is the rspec group instance,
# arg are the arguments to the function. I can''t see a
# way to get the actual <Model> instance :(
save_count+=1
end
.... run the test here ...
save_count.should > 0
Parece que el método stub se puede adjuntar a cualquier instancia sin la restricción, y el bloque do puede hacer un conteo que se puede verificar para afirmar que se llamó el número correcto de veces.
Actualización: la nueva versión de rspec requiere esta sintaxis:
save_count = 0
allow_any_instance_of(Model).to receive(:save) do |arg|
# The evaluation context is the rspec group instance,
# arg are the arguments to the function. I can''t see a
# way to get the actual <Model> instance :(
save_count+=1
end
.... run the test here ...
save_count.should > 0
Este es el ejemplo de Rob que usa RSpec 3.3, que ya no es compatible con Foo.any_instance
. Lo encontré útil cuando estaba en un bucle creando objetos
# code (simplified version)
array_of_hashes.each { |hash| Model.new(hash).write! }
# spec
it "calls write! for each instance of Model" do
call_count = 0
allow_any_instance_of(Model).to receive(:write!) { call_count += 1 }
response.process # run the test
expect(call_count).to eq(2)
end
Finalmente logré hacer una prueba que me funciona:
mutation = FactoryGirl.build(:mutation)
Mutation.stub(:new).and_return(mutation)
mutation.should_receive(:save).at_least(:once)
El método stub devuelve una sola instancia que recibe el método guardar varias veces. Debido a que es una instancia única, puedo descartar el método any_instance
y usar el método at_least
normalmente.
Hay una nueva sintaxis para esto:
expect_any_instance_of(Model).to receive(:save).at_least(:once)
Mi caso fue un poco diferente, pero terminé con esta pregunta y pensé que soltaría mi respuesta aquí también. En mi caso, quería resguardar cualquier instancia de una clase determinada. expect_any_instance_of(Model).to
el mismo error cuando utilicé expect_any_instance_of(Model).to
. Cuando lo cambié a allow_any_instance_of(Model).to
, mi problema fue resuelto.
Consulte la documentación para obtener más información: github.com/rspec/…
Stub como este
User.stub(:save) # Could be any class method in any class
User.any_instance.stub(:save) { |*args| User.save(*args) }
Entonces espera así:
# User.any_instance.should_receive(:save).at_least(:once)
User.should_receive(:save).at_least(:once)
Esta es una simplificación de esta esencia , para usar any_instance
, ya que no es necesario utilizar el método original. Consulte esa idea para otros usos.