Search code examples
ruby-on-railsrubyrspeccontrollers

RSpec Controller Testing


I am new to testing with RSpec and I would really appreciate your help.

This is my index action inside the controller and I need to make tests for it to see if the chained selects inside the view are acting as they are supposed to. I would be grateful for any code you could provide me with, since I am not even sure where to start with this.

def index
 respond_to do |format|
  format.html
  format.json do
    if params[:s_id].blank? && !params[:f_id].blank?
      @fp_for_dropdown = Model.where(:f_id => params[:f_id])
    elsif !params[:s_id].blank? && params[:f_id].blank?
      @fp_for_dropdown = Model.where(:s_id => params[:s_id])
    elsif !params[:s_id].blank? && !params[:f_id].blank?
        @fp_for_dropdown = Model.where(:s_id => params[:s_id], :f_id => params[:f_id])
    else
      @fp_for_dropdown = Hash[]
    end
    render :json => Hash["" => ""].merge(Hash[@fp_for_dropdown.map { |i| [i.id, i.name] }])
  end
end

end


Solution

  • One approach to this problem is to think of your controller tests as unit tests. That means mocking out the calls to Model to make sure the correct ones are called.

    describe SomeController do
      it 'should retrieve by s_id only' do
        Model.should_receive(:where).with(:s_id => 'abc')
        get :index, :s_id => 'abc'
      end
      it 'should retrieve by f_id only' do
        Model.should_receive(:where).with(:f_id => 'abc')
        get :index, :f_id => 'abc'
      end
      it 'should retrieve by f_id and s_id' do
        Model.should_receive(:where).with(:f_id => 'abc', :s_id => '123')
        get :index, :f_id => 'abc', :s_id => '123'
      end
      it 'should not hit the database without f_id or s_id' do
        Model.should_not_receive(:where)
        get :index
      end
    end
    

    If you want to get fancy, you can also test the response json:

    it 'should retrieve by f_id only' do
      Model.should_receive(:where).with(:f_id => 'abc').and_return(OpenStruct.new(id: 'abc', name: '123'))
      get :index, :f_id => 'abc'
      JSON.parse(response.body).should == {} # INCOMPLETE, fill in response to expect
    end
    

    Unfortunately, I couldn't complete the response checking because I do not know what you are doing with the Hashes in this line:

    render :json => Hash["" => ""].merge(Hash[@fp_for_dropdown.map { |i| [i.id, i.name] }])
    

    Take a look at jbuilder or rabl for constructing JSON responses with views.