Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to say "any_instance" "should_receive" any number of times in RSpec

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?

like image 410
Harm de Wit Avatar asked Mar 21 '12 08:03

Harm de Wit


People also ask

What is stubbing in RSpec?

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.

What is RSpec double?

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.

What is allow in RSpec?

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.

What does RSpec describe do?

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.


2 Answers

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 
like image 151
Rob Avatar answered Oct 12 '22 22:10

Rob


There's a new syntax for this:

expect_any_instance_of(Model).to receive(:save).at_least(:once) 
like image 33
muirbot Avatar answered Oct 12 '22 20:10

muirbot