0

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

BlueIvy
  • 67
  • 2
  • 10

2 Answers2

0

There's a good reason these queries are difficult to test in a controller-- they don't belong there. Instead, it would be better to move them into either class methods or scopes on your model, which you then call from your controller. Then you can write regular RSpec model specs.

See: How to test scopes?

Community
  • 1
  • 1
Josh Rieken
  • 2,256
  • 1
  • 19
  • 23
  • I know it would be better, but for some reason the code I am working at has it at the controller so I will leave it like that at the moment. Thanks for the links, will take a closer look to it. – BlueIvy Jan 19 '13 at 22:46
0

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.

accounted4
  • 1,685
  • 1
  • 11
  • 13