0
votes

I'm now making Rspec for controller SearchController. This controller do search record by sql with parameter which was got by "get" request. The controller is as follow.

class SearchController < ApplicationController

  def index
    if params[:category] == 'All'
      @search_result = Item.find_by_sql("SELECT * FROM items WHERE name LIKE '%# {params[:name]}%'")
    else
      @search_result = Item.find_by_sql("SELECT * FROM items WHERE name LIKE '%#{params[:name]}%' AND category = '#{params[:category]}'")
    end
    if @search_result.empty? then
      redirect_to main_app.root_path, notice: "No items found matching your search criteria ! Modify your search."
    else
      @search_result=@search_result.paginate(:page => params[:page],:per_page => 3)
    end
  end
 end

Then I wrote simple Rspec test as follow. This test intends that at first the object item is made to use in controller. Also the stub (Item.stub(:find_by_sql).and_return(item)) is declared. Then do get :index with parameter :category => 'All'. My expect is that in the controller if params[:category] == 'All' is passed and @search_result is filled by object. (As I mentioned, the stub was already declared. Also object was already made. Then Item.find_by_sql(*****) would return object which was already declared.)

require 'spec_helper'

describe SearchController do

  let(:valid_session) { {} }

  describe "" do
     it "" do
      item = Item.new(auction_id:'1',min_bid_price:'100.0')
      item.save
      Item.stub(:find_by_sql).and_return(item)

      get :index, {:category => 'All'}, valid_session

      @search_result.should_not be_empty

     end
  end
end

Then I ran Rspec and unfortunately got the error as follow. I think @search_result could not be successfully filled with object, so "empty?" could not be called. However I have no idea about how to fix this. I already use many hours about this. I would like to have someone's help.

Failures:

  1) SearchController
     Failure/Error: get :index, {:category => 'All'}, valid_session
     NoMethodError:
     undefined method `empty?' for #<Item:0x523c980>
     # ./app/controllers/search_controller.rb:9:in `index'
     # ./spec/controllers/search_controller_spec.rb:13:in `block (3 levels) in <top (required)>'

     Finished in 0.25 seconds
     1 example, 1 failure

  Failed examples:

     rspec ./spec/controllers/search_controller_spec.rb:8 # SearchController

     Randomized with seed 50151 
2

2 Answers

4
votes

The problem is here:

Item.stub(:find_by_sql).and_return(item)

You are stubbing find_by_sql and returning a single item instead of a collection of items. The simple fix is to wrap it in an array:

Item.stub(:find_by_sql).and_return [item]

Note that this will only work if Array is modified to support paginate (will_paginate will do this if you require the `will_paginate/array' library).

Aside from this, as @PeterAlfvin has mentioned, you have a mistake near the end of your spec:

@search_result.should_not be_empty

Should actually be written as:

assigns(:search_result).should_not be_empty

This is because you can't access instance variables assigned by your controller action directly.

1
votes

While the error is occurring in your model, you also have a problem in your example.

You seem to be assuming that because @search_result is defined in the controller, it is directly accessible in your RSpec example. That is not the case. @search_result is nil in the example because you have not assigned a value to it.

You can, however, access the @search_result instance variable in the controller through the RSpec assigns method, as in assigns[:search_result].