Rails模型验证和测试

时间:2015-12-02 13:29:25

标签: ruby-on-rails validation activerecord

我有一个简单的Rails 4应用程序,我试图编写一些测试来检查我的用户注册是否正常工作。 我有一个问题,当我用我的手运行测试用例时,一切正常,但是当我编写一些集成测试并运行它时,它会跳过我的模型的验证,所以我得到了数据库异常喜欢

Minitest::UnexpectedError: ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_users_on_username"


test 'unique username violated' do
    params = user_params               # it is just a hash with User model attributes
    User.new(params).save              # saving user first time to violate unique after        
    params[:email] = 'Test@Email2'
    assert_no_difference 'User.count' do
        post users_path, user: params
    end
    assert_template 'users/new'
end

我的验证示例如下:

validates :username, :email, \
  uniqueness: {uniqueness: true, message: 'Username&email must be unique'}, \
  length: {maximum: 50, message: 'Length must be <= 50'}

不仅是这个验证问题,而且所有其他问题也不在测试中。

如果我在测试中使用类似的东西来验证我的用户对象,那么它应该是假的。

User.new(params).valid?

我的用户#create action如下:

def create
    @user = User.new user_params
    if @user.save
        flash[:success] = 'Welcome to the Sample App!'
        redirect_to @user
    else
        render 'new'
    end
 end

我的用户#user_params方法:

def user_params
    user_group = UserGroup.find_by_name 'administrator'
    if user_group.nil?
        user_group = UserGroup.new name: 'administrator'
        user_group.save
    end
    {username: 'TestUsername', password: 'TestPassword', \
password_confirmation: 'TestPassword', email: 'Test@Email', \
firstname: 'TestFirstname', lastname: 'TestLastname',user_group: user_group}
end

1 个答案:

答案 0 :(得分:0)

Rails验证并没有真正起作用。当你使用:

validates :username, :email, uniqueness: true

您正在为:username:email添加类似但独立的验证。考虑这种情况:

user = User.new
user.valid?
assert(user.errors.has_key?(:username)) # pass
assert(user.errors.has_key?(:email)) # pass

当您使用user.errors.full_messages()打印出错误时,它会同时包含Email has already been takenUsername has already been taken

但如果你覆盖这样的消息:

validates :username, :email, uniqueness: { message: 'Username&email must be unique' }

你会得到Username&email must be unique两次,这不是很好。

如果出于某种原因,您确实只需要一个错误,则可以添加自定义验证方法:

validate :uniqueness_of_username_and_email

def uniqueness_of_username_and_email
  if User.where("username = ? OR email = ?", username, email).any?
    errors.add(:email_username, 'Username&email must be unique')
  end
end