Rails 3 - 通过rspec对PUT方法进行正确测试

时间:2012-04-07 11:52:07

标签: ruby-on-rails-3 model-view-controller model rspec rspec-rails

我有模型 TeacherLeader ,它为其他表保留外键。我可以更新这个表,我尝试为我的控制器编写测试(通过rspec)。

我的模特:

#  id         :integer         not null, primary key
#  user_id    :integer
#  teacher_id :integer
#

class TeacherLeader < ActiveRecord::Base  
  belongs_to :user
  belongs_to :teacher

  validates :teacher_id, 
              :uniqueness => { :message => "already a class-head" }
end

我的控制器

class TeacherLeadersController < ApplicationController
 def edit
    @teacher_leader = TeacherLeader.find( params[:id] )    
    ...
  end

  def update
    @teacher_leader = TeacherLeader.find( params[:id] )
    ...

    if ( @teacher_leader.update_attributes( params[:teacher_leader] ) )                   
      redirect_to teachers_path
      ...
    else
      redirect_to edit_teacher_leader_path
      ...
      end      
    end
  end
end

所以,我在为PUT编写测试时遇到了问题。以下是我的PUT方法代码示例:

describe TeacherLeadersController do
  render_views

  before(:each) do    
    @teacher = Factory( :teacher )
    @teacher.user.user_role = "teacher"
    @teacher.save!

    @user = Factory( :user, :user_login => Factory.next(:user_login) )
    @user.user_role = "class_head"
    @user.save!

    @sh = Factory( :user, :user_login => Factory.next(:user_login)  )
    @sh.user_role = "school_head"
    @sh.save!
  end

  describe "PUT 'update" do
    before(:each) do
      @teacher_leader = @user.create_teacher_leader( @attr_teacher_leader )
    end

    describe "for signed-in school-heads" do
      before(:each) do
        test_sign_in( @sh )
      end

      it "should update teacher leader with correct params" do
        put :update, :id => @teacher_leader, :teacher_id => @teacher.id
        @teacher_leader.reload
        @teacher_leader.teacher_id.should  == @teacher.id
      end
    end
  end
end

当我尝试运行我的规格时,我得到了:

1) TeacherLeadersController PUT 'update for signed-in school-heads should update teacher leader with correct params
     Failure/Error: put :update, :id => @teacher_leader, :teacher_id => @teacher.id
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # ./app/controllers/teacher_leaders_controller.rb:57:in `update'
     # ./spec/controllers/teacher_leaders_controller_spec.rb:150:in `block (4 levels) in <top (required)>'

但我的申请有效!我在测试中做错了什么?

2 个答案:

答案 0 :(得分:6)

您的控制器需要params[:teacher_leader]哈希,但您的测试不提供它。试试这个:

it "should update teacher leader with correct params" do
  put :update, :id => @teacher_leader, :teacher_leader => { :teacher_id => @teacher.id }
  # ...

答案 1 :(得分:2)

确保您的规范包含describe TeacherLeadersController块。例如:

describe TeacherLeadersController do
  describe "PUT 'update" do
    #...

    describe "for signed-in school-heads" do
      it "should update teacher leader with correct params" do
        put :update, :id => @teacher_leader, :teacher_id => @teacher.id
      end
    end
  end
end

..那么您应该能够正确使用put方法。

此外,您忘记将:teacher_leader属性传递给测试下的控制器。试试put :update, :id => something, :teacher_leader => { some_attributes_here }

无论如何,我强烈建议您在控制器规范中模拟所有数据库查询(活动记录调用)。为了测试params是否持久化,您应该使用请求规范(或其他方法进行集成/验收测试)。例如,请参阅:http://blog.bandzarewicz.com/slides/krug-the-perfect-rspec/#27