2

我有模型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)>'

但我的应用程序有效!我在测试中做错了什么?

4

2 回答 2

6

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

it "should update teacher leader with correct params" do
  put :update, :id => @teacher_leader, :teacher_leader => { :teacher_id => @teacher.id }
  # ...
于 2012-04-07T12:37:38.757 回答
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 }

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

于 2012-04-07T12:41:51.127 回答