Search code examples
ruby-on-railsrspecpartialrender-to-string

rails render_to_string problem


I`m trying to test my controller with rspec and always get an error.

users_controller.rb:

def update
    @user.update_attributes!(params[:user])

    redirect_to @user, :status => 202, :text => render_to_string(:partial => "users/show", :type => "json", :locals => {:user => @user})
    #notice, that redirect_to was reinitialized and :text is a parameter for response_body
end
_show.tokamak
user {
  id user.id
  email user.email
  username user.username
}
spec file
it "should NOT update user username" do
      username = @user.username
      put 'update', :id => @user.id, :user => {:username => username+"abc"}, :format => :json
      response.status.should be(202) 
      response.headers["Location"].length.should be > 0
      puts response.body
      @user.reload
      @user.username.should eq(username)
      end
    end

So I get an error:

Failure/Error: put 'update', :id => @user.id, :user => {:username => username+"abc"}, :format => :json ActionView::Template::Error: You have a nil object when you didn't expect it! You might have expected an instance of Array. The error occurred while evaluating nil.[] # C:/Users/makaroni4/free_frog/ffapi/app/views/users/_show.tokamak:1:in _app_views_users__show_tokamak___509498818 _32151168_368311673' # C:/Users/makaroni4/XXX/XXX/app/controllers/users_controller.rb:22:in update' # ./users_controller_spec.rb:34:in `block (4 levels) in '

So may be I call render_to_string method wrong?


Solution

  • Try stubbing out find?

    mock_user = User.stub(:find).with(@user.id) {@user}
    

    To be honest I'd go a few steps further and make sure you mock and stub most of the relevant behavior of the User object (or whatever class @user is). Keep in mind you're only testing that the controller action returns what you expect if you give it valid input--not that the model itself does the right thing.

    I had a lot of difficulty wrapping my head around the differences in model vs. controller specs...

    I hope this helps...if not, I apologize in advance...

    EDIT:

    I'll take this a step futher and suggest this test is actually a model test. The actual controller test would be something like as the way your spec test should behave:

    it "should NOT update user with invalid input" do
      mock_user = mock_model(User, {}).as_null_object
      User.stub(:find).with("12") {mock_user}
      User.stub(:update_attributes).with({}).and_return(false)
      put 'update', :id => "12"
    
      # test that your output is correct, or even if the render target is what you expect.
    
    end