Topic: Basic test that is failing, probably something simple

I have a test that I can't get to pass and since I am new to TDD I really am not sure of my options on how to get it passing. In basic english. I have a project and a todo_item. todo_item belong to projects, projects have many todo_items. When I update a todo_item it should redirect to its project page. Simple enough. Here is the test:

it "update action should redirect when model is valid" do
    TodoItem.any_instance.stubs(:valid?).returns(true)
    todo = TodoItem.first
    put :update, :id => todo
    response.should redirect_to(project_url(todo.project))
  end

The failure message is:

 TodoItemsController update action should redirect when model is valid
     Failure/Error: put :update, :id => todo
     ActionController::RoutingError:
       No route matches {:controller=>"todo_items", :action=>"update", :id=>nil}
     # ./spec/controllers/todo_items_controller_spec.rb:61

Now when I run through the browser it works just fine, so I am fairly sure its not the app code. No TodoItems are getting created so TodoItem.first never finds I record. I dont think that I have anything overly complicated, but I just cant get it work no matter what I try. Any help and suggestions would be greatly appreciated.

Re: Basic test that is failing, probably something simple

As error message states, it tries to pass a nil id to the todo_items#update. Try doing

put :update, :id => todo.id

instead of

put :update, :id => todo

Re: Basic test that is failing, probably something simple

bluesman.alex thanks for the reply. When I try what you suggested I a similar, but different error

TodoItemsController update action should redirect when model is valid
Failure/Error: put :update, :id => todo.id
RuntimeError:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
# ./spec/controllers/todo_items_controller_spec.rb:61

So I am still dealing with the nil, although I believe that this confirms that no TodoItem is every getting created so the call to TodoItem is returning nil. Any other suggestions? When I stub, can I specify and ID for the objects parent? or even if I could do that is that bad practice when stubbing?

Re: Basic test that is failing, probably something simple

Hmm... Right, you should create a todo item smile

Instead of doing

todo = TodoItem.first

do

todo = TodoItem.create(...)

Even better - use factory_girl for creating models in specs.

You can still stub with any_instance, I think it'll be just fine.
There are ways to stub methods on model with certain id, but I rarely do it, because its not beautiful at all smile

It looks something like this (just the general sense, not tested):

original_find = TodoItem.method(:find)
TodoItem.stub(:find) do |*args|
  result = original_find.call(args)
  if result.id == expected_id
    result.stub(:valid?).and_return(true)
  end
  result
end

Looks ugly, eh? This is a code for rspec's own mocking. I believe with mocha it would require more metaprogramming smile