Reputation: 307
I have the following request spec
it "updates an open time" do
# Create an OpenTime
open_time = OpenTime.create(:start_time => (Time.now + 2.hours), :end_time => (Time.now + 10.hours))
# Build an open_time update param
params = {:open_time => {:start_time => (Time.now + 5.hours)}}
# Send param to open_times#update
put open_time_path(open_time.id) , params
# Check to see if OpenTime was updated
open_time.should_receive(:update_attributes).with({:start_time => (Time.now + 5.hours)})
end
Here is my open_times controller
def update
@open_time = OpenTime.find(params[:id])
if @open_time.update_attributes(params[:open_time])
flash[:success] = "Time updated."
redirect_to @open_time
else
render 'edit'
end
end
Test is failing with expected : 1 received: 0
Upvotes: 1
Views: 128
Reputation: 6931
As kr1 noticed you have to stub OpenTime.find method to return your instance of OpenTime when it gets called from the controller. Change your test code to:
it "updates an open time" do
target_time = (Time.now + 5.hours)
# Create an OpenTime
open_time = OpenTime.create(:start_time => (Time.now + 2.hours), :end_time => (Time.now + 10.hours))
# Build an open_time update param
params = {:open_time => {:start_time => target_time}}
# Stub OpenTime to return your instance
OpenTime.stub(:find).and_return(open_time)
# Set expectation on open_time to receive :update_attributes
open_time.should_receive(:update_attributes).with({:start_time => target_time})
# Send param to open_times#update
put open_time_path(open_time.id) , params
end
What is happening here is that you build your instance of OpenTime(open_time) and by stubbing OpenTime class you are saying "if someone call find on OpenTime class don't run find but simply return open_time(instance you just created)". Then you set up expectation on your instance to receive :update_attributes. When you call put open_time_path(open_time.id) , params your controller create action will process request and OpenTime.find(...) will return your instance(open_time) and call :update_attribute on it.
Hope it make a sense.
Upvotes: 1
Reputation: 7485
it is not that object that will receive update_attributes
, but a new object returned by OpenTime.find
, therefore, you should make sure that find returns your object:
OpenTime.stub(:find).and_return(open_time)
open_time.should_receive(:update_attributes).with({:start_time => (Time.now + 5.hours)})
and then:
put open_time_path(open_time.id) , params
additionaly, I would add target_time = Time.now + 5.hours
at the beginning of the test, and then use that time in params and matcher.
Upvotes: 1