已经完成了找出某些rspec测试失败原因的任务。我没有写任何代码,而且卡住了。这是输出:
3) PeopleController create action should redirect when model is valid
Failure/Error: post :create
TypeError:
no implicit conversion of nil into String
# ./app/models/person.rb:24:in `digest'
# ./app/models/person.rb:24:in `hexdigest'
# ./app/models/person.rb:24:in `encrypt_password'
# ./app/models/person.rb:30:in `prepare_password'
# ./app/controllers/people_controller.rb:10:in `create'
# ./spec/controllers/people_controller_spec.rb:20:in `block (2 levels) in <top (required)>'
这是people_controller_spec:
require File.dirname(__FILE__) + '/../spec_helper'
describe PeopleController do
fixtures :all
render_views
it "new action should render new template" do
get :new
response.should render_template(:new)
end
it "create action should render new template when model is invalid" do
Person.any_instance.stub(:valid?).and_return(false)
post :create
response.should render_template(:new)
end
it "create action should redirect when model is valid" do
Person.any_instance.stub(:valid?).and_return(true)
post :create
response.should redirect_to(root_url)
session['person_id'].should == assigns['person'].id
end
it "show action should redirect when not logged in" do
get :show, :id => "ignored"
response.should redirect_to(login_url)
end
it "show action should render show template" do
@controller.stub(:current_user).and_return(Person.first)
get :show, :id => "ignored"
response.should render_template(:show)
end
end
以下是失败的people_controller的代码块:
def create
@person = Person.new(:username => params[:username], :password => params[:password], :first_name => params[:first_name], :last_name => params[:last_name])
if @person.save
session[:person_id] = @person.id
if Invite.where(:ad_username => @person.username).count != 0
organization = Organization.find(Invite.where(:ad_username => @person.username).first.organization_id)
Affiliation.create!(:organization_id => organization.id, :person_id => @person.id, :affiliation_type => Affiliation::ATHLETIC_DIRECTOR)
end
redirect_to root_url, :notice => "Thank you for signing up! You are now logged in."
else
render :action => 'new'
end
end
以下是人物模型:
class Person < ActiveRecord::Base
# new columns need to be added here to be writable through mass assignment
attr_accessible :username, :password, :password_confirmation, :first_name, :last_name, :cell_phone
has_one :affiliation, :dependent => :destroy
has_many :contacts, :dependent => :destroy
before_save :prepare_password
before_validation :downcase_username
validates :username, :uniqueness => {:case_sensitive => false}
validates_presence_of :username, :first_name, :last_name
validates_format_of :username, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i, :message => " must be a valid email"
validates_presence_of :password, :on => :create
validates_confirmation_of :password
validates_length_of :password, :minimum => 4
def self.authenticate(login, pass)
person = find_by_username(login.downcase)
return person if person && person.password == person.encrypt_password(pass)
end
def encrypt_password(pass)
Digest::SHA1.hexdigest(pass)
end
private
def prepare_password
self.password = encrypt_password(password)
end
def downcase_username
self.username = self.username.downcase if self.username.present?
end
end
我无法弄清楚这会被绊倒。
答案 0 :(得分:2)
错误是由nil:密码引起的。看起来像before_save:prepare_password过滤器正在运行并抛出该错误。但是使用before_save似乎不正确,因为每次更新人员时都会发生这种情况,每次都会重新加密密码。将它更改为before_create所以它只发生一次。如果它仍然抛出错误,你可以做一些事情来解决它,或者:
def encrypt_password(pass)
Digest::SHA1.hexdigest(pass.to_s) # will change nils into strings and this won't blow up
end
或在您的测试用例中添加密码参数:
it "create action should render new template when model is invalid" do
Person.any_instance.stub(:valid?).and_return(false)
post :create, :password => "" # invalid password
response.should render_template(:new)
end
这样控制器将收到params[:password]
并将字符串传递给Person.new
。