Rspec - RuntimeError:nil的被调用id,错误地为4

时间:2013-11-22 15:13:37

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

我现在正在对create ItemsController的{​​{1}}动作进行Rspec测试,但是我对这个错误感到麻烦。 (模型有ItemAuctionBidUser

create方法如下

 # POST /items
 # POST /items.json
 def create
   @item = Item.new(params[:item])
   @item.user_id = current_user.id

   respond_to do |format|
     if @item.save
       format.html { redirect_to @item, notice: 'Item was successfully created.' }
       format.json { render json: @item, status: :created, location: @item }
     else
       format.html { render action: "new" }
       format.json { render json: @item.errors, status: :unprocessable_entity }
     end
   end
   @elapsed_seconds =(((params[:item][:days].to_i * 24)+params[:item][:hours].to_i)*60+params[:item][:minutes].to_i)*60
   @auction = Auction.create(:item_id => @item.id, :highest_bid_id => 0, :exp_time =>             
   @item.created_at+ @elapsed_seconds.seconds, :suspend => 0, :user_id => @current_user.id, :extend_bit => 0 )
   @item.update_attributes(:auction_id => @auction.id)
   @item_id = @item.id
   @auction_id = @auction.id
   @t1 = Thread.new{
     @timer = Timers.new
     @bid_timer = @timer.after(@elapsed_seconds){
       if Auction.find_by_id(@auction_id).suspend != 1
          buy
       end
     }
   @timer.wait
   }

end

def buy
  if Auction.find_by_id(@auction_id).extend_bit == 1
    extendtimer
  else
    if Auction.find_by_id(@auction_id).highest_bid_id != 0
      Item.find_by_auction_id(@auction_id).update_attributes(:sold => 1, :sold_to => Bid.find_by_id(Auction.find_by_id(@auction_id).highest_bid_id).user_id )
      MyMailer.auction_winner_email(Auction.find_by_id(@auction_id)).deliver
    else
      Item.find_by_auction_id(@auction_id).update_attributes(:sold => 0, :sold_to => 0 )
      MyMailer.no_bids_email(Auction.find_by_id(@auction_id)).deliver
    end
    @t1.join
  end
end

def extendtimer
    Auction.find_by_id(@auction_id).update_attributes(:extend_bit => 0)
    @exp = Auction.find_by_id(@auction_id).exp_time + 2.minutes
    Auction.find_by_id(@auction_id).update_attributes(:exp_time => @exp)
    @min = Item.find_by_id(@item_id).minutes + 2
    Item.find_by_id(@item_id).update_attributes(:minutes => @min)
    @timer2 = Timers.new
    @extend_timer = @timer2.after(120){ buy }
    @timer2.wait
end

我的Rspec如下。此测试旨在首先使用对象(例如current_userauction,“item ). Then also stubs are declared. (such as Auction.stub(:find_by_id).and_return(auction)`)

require 'spec_helper'

describe ItemsController do

  let(:valid_session) { {} }

  describe "POST create" do
    it "" do
      #declare the objects and stubs
      current_user = User.new(id:'1')
      current_user.save
      auction = Auction.new(id:'1',highest_bid_id:'1', extend_bit:'1')
      auction.save
      Auction.stub(:find_by_id).and_return(auction)
      bid = Bid.new(auction_id:'1',amount:'150.0')
      bid.save
      Bid.stub(:find_by_id).and_return(bid)
      item = Item.new(id:'1',auction_id:'1',min_bid_price:'100.0')
      item.save
      Item.stub(:find_by_id).and_return(item)

      #POST create 
      post :create, {:item => {'id' => '2','days'=>'1','hours'=>'1','minutes'=>'1'}}

      response.should redirect_to(@item)
      flash[:notice].should eql("Item was successfully created.")


    end
  end
end

不幸的是我跑了Rspec,我得到了如下错误。我认为@item无法成功创建控制器中的@item = Item.new(params[:item]),因此可能会发生此错误。但是我找不到如何修复。我已经用了好几个小时了。我想得到别人的帮助。

故障:

1) ItemsController POST create
 Failure/Error: post :create, {:item => {'id' => '2','days'=>'1','hours'=>'1','minutes'=>'1'}}
 RuntimeError:
   Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
 # ./app/controllers/items_controller.rb:72:in `create'
 # ./spec/controllers/items_controller_spec.rb:19:in `block (3 levels) in <top (required)>'

 Finished in 0.637 seconds 1 example, 1 failure

 Failed examples:

  rspec ./spec/controllers/items_controller_spec.rb:11 # ItemsController POST create

  Randomized with seed 33483  

1 个答案:

答案 0 :(得分:2)

由于没有人登录,current_user方法返回nil。在规范中设置局部变量current_user对此没有帮助。相反,您可以定义ApplicationController#current_user=方法:

def current_user=(user)
  @current_user ||= user
end

并在您的规范中调用它:

controller.current_user = current_user