Rspec错误 - NoMethodError:未定义的方法`空?'

时间:2013-11-22 16:05:07

标签: ruby-on-rails ruby ruby-on-rails-3 rspec rspec-rails

我现在为控制器SearchController制作Rspec。该控制器通过sql搜索记录,参数由“get”请求获得。控制器如下。

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

然后我写了简单的Rspec测试如下。此测试旨在首先使对象item在控制器中使用。还声明了存根(Item.stub(:find_by_sql).and_return(item))。然后使用参数get :index执行:category => 'All'。我希望在控制器if params[:category] == 'All'中传递,@search_result由对象填充。 (正如我所提到的,已经声明了存根。还有对象已经完成。然后Item.find_by_sql(*****)将返回已经声明的对象。)

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

然后我跑了Rspec,不幸的是得到了如下错误。我认为@search_result无法成功填充对象,所以“空”?无法调用。但是我不知道如何解决这个问题。我已经用了好几个小时了。我想得到别人的帮助。

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 个答案:

答案 0 :(得分:4)

问题在于:

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

您正在查找find_by_sql并返回单个项而不是项集合。简单的解决方法是将其包装在一个数组中:

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

请注意,只有在修改Array以支持paginate时才会这样做(如果需要`will_paginate / array'库,will_paginate会执行此操作。)

除此之外,正如@PeterAlfvin所提到的,你的规范即将结束时出现错误:

@search_result.should_not be_empty

实际上应该写成:

assigns(:search_result).should_not be_empty

这是因为您无法直接访问控制器操作分配的实例变量。

答案 1 :(得分:1)

虽然模型中出现错误,但您的示例中也存在问题。

您似乎在假设因为@search_result是在控制器中定义的,所以可以在RSpec示例中直接访问它。事实并非如此。 <{1}}在示例中为@search_result,因为您尚未为其指定值。

可以通过RSpec nil方法访问控制器中的@search_result实例变量,如assigns