I've got an import controller in rails that imports several csv files with multiple records into my database. I would like to test in RSpec if the records are actually saved by using RSpec:
<Model>.any_instance.should_receive(:save).at_least(:once)
However i get the error saying:
The message 'save' was received by <model instance> but has already been received by <another model instance>
A contrived example of the controller:
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
Is it possible to test this using RSpec or is there any workaround?
In RSpec, a stub is often called a Method Stub, it's a special type of method that “stands in” for an existing method, or for a method that doesn't even exist yet. Here is the code from the section on RSpec Doubles − class ClassRoom def initialize(students) @students = students End def list_student_names @students.
RSpec features doubles that can be used as 'stand-ins' to mock an object that's being used by another object. Doubles are useful when testing the behaviour and interaction between objects when we don't want to call the real objects - something that can take time and often has dependencies we're not concerned with.
Use the allow method with the receive matcher on a test double or a real. object to tell the object to return a value (or values) in response to a given. message. Nothing happens if the message is never received.
The word describe is an RSpec keyword. It is used to define an “Example Group”. You can think of an “Example Group” as a collection of tests. The describe keyword can take a class name and/or string argument.
Here's a better answer that avoids having to override the :new method:
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
Seems that the stub method can be attached to any instance w/o the constraint, and the do block can make a count that you can check to assert it was called the right number of times.
Update - new rspec version requires this syntax:
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
There's a new syntax for this:
expect_any_instance_of(Model).to receive(:save).at_least(:once)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With