views:

1091

answers:

1

I have the following controller action and test. I'm new to testing with Shoulda and I know there are areas of my controller that I can test further. For example, my flash messages as well as verifying the renders.

So my question is, how would I properly test this controller action in Shoulda?

My controller action (names have been changed to protect the innocent):

def my_action
  return redirect_to(root_url) if @site.nil?
  @owner = current_site.owner
  if request.post?
    if params[:password].blank? || params[:email].blank?
      flash[:error] = "You must fill in both the e-mail and password fields"
      render :action => "my_action"
    else
      if @owner.authenticated?(params[:password])
        @owner.login = params[:email]
        @owner.save!
        @owner.do_some_method
        flash[:success] = "Success."
        render :action => "my_action"
      else
        flash[:error] = "Incorrect password"
        render :action => "my_action"
      end
    end      
  end  
end

My test:

context "on POST to :my_action" do
  setup do
    Owner.any_instance().expects(:do_some_method)
    post :my_action, :email => '[email protected]', :password => 'test'
  end
  should_assign_to :owner
  should "Change name and verify password and resend activation key" do
    assert_equal true, assigns(:owner).authenticated?('test')
    assert_equal '[email protected]', assigns(:owner).login
  end
  should_respond_with :success
end
+2  A: 

Right now, it appears that you're testing functionality specific to the model inside your controller, that should be in a unit test.

I would advise re-factoring your controller to include the required logic for updating the Owner's email inside the Owner model. By doing that, you should be able to simplify the controller down to a simple if update; else; end type statement and greatly simplify the controller test. Once you've moved the logic into the model, you can use built in Rails validations.

A couple of other things to consider:

  • Redirecting after your POST action completes, prevents the user from double-posting by accident (most browsers will complain when the user attempts it).
  • Move the checking for @site and also the assignment to @owner to before_filters if this is done more than once inside the controller.
  • You can avoid having to check if request.post? with either verify or creating a route in `config/routes.rb'.

References:

Matt Haley