新手问题 数据库约束了 null false 后,做空值 test 会报 error

thanatos · 2015年07月29日 · 最后由 thanatos 回复于 2015年07月30日 · 2065 次阅读

做 model 的时候,在数据库层约束了 null 是 false,然后又在 model 本身加上了 validates presence: true。现在写 test,当尝试为其赋空值时,期望得到这个 record 没有添加成功,不想 test 直接给了 error,说 ActiveRecord::RecordInvalid: Validation failed: Assetnum(就是那个不能为空的字段)can't be blank。 请问这样的测试应该怎么写?谢谢! 贴代码: 先建表,

create_table "hardwares", force: :cascade do |t|
    t.string   "AssetNum",        null: false
  #此处省略若干其他字段
    t.datetime "created_at",      null: false
    t.datetime "updated_at",      null: false
  end

然后做 model

class Hardware < ActiveRecord::Base
  validates :AssetNum, presence: true
end

create 动作是酱紫的

class HardwaresController < ApplicationController
  def new
    @hardware = Hardware.new
  end

  def create
    @hardware = Hardware.new(hardware_params)
    @hardware.save!
    redirect_to @hardware
  end
  private
    def hardware_params
      params.require(:hardware).permit(:AssetNum, :CPU, :Disk1Size, :Disk1Num,
                                       :Disk2Size, :Disk2Num, :Disk3Size,
                                       :Disk3Num, :Mem1Size, :Mem1Num, :Mem2Size,
                                       :Mem2Num, :BuyingTime, :DeployingTime,
                                       :Position, :ServerType, :ServerModel,
                                       :ServiceNum, :QuickServiceNum )
    end
end

程序到这里都 OK,可以正常的创建,于是我做了一个 test 来检测提交空值的 AssetNum 会不会创建这个记录,如下

class CreateHardwareTest < ActionDispatch::IntegrationTest

  def setup
    @h1 = hardwares(:h1)
  end

test "create hardware with invalid information" do

    assert_no_difference 'Hardware.count' do
      post hardwares_path, hardware: {
                             AssetNum: "" ,
                             CPU: @h1.CPU ,
                             Disk1Size: @h1.Disk1Size ,
                             Disk1Num: @h1.Disk1Num ,
                             Mem1Size: @h1.Mem1Size ,
                             Mem1Num:  @h1.Mem1Num ,
                             BuyingTime: @h1.BuyingTime ,
                             DeployingTime: @h1.DeployingTime ,
                             Position: @h1.Position ,
                             ServerType: @h1.ServerType ,
                             ServerModel: @h1.ServerModel ,
                             ServiceNum: @h1.ServiceNum ,
                             QuickServiceNum: @h1.QuickServiceNum
                         }
    end
  end
end

理论上来说 OK 的,但是跑测试的结果却是:

ERROR["test_create_hardware_with_invalid_information", CreateHardwareTest, 2015-07-29 08:39:36 +0800]
 test_create_hardware_with_invalid_information#CreateHardwareTest (1438130376.94s)
ActiveRecord::RecordInvalid:         ActiveRecord::RecordInvalid: Validation failed: Assetnum can't be blank
            app/controllers/hardwares_controller.rb:13:in `create'
            test/integration/create_hardware_test.rb:39:in `block (2 levels) in <class:CreateHardwareTest>'
            test/integration/create_hardware_test.rb:38:in `block in <class:CreateHardwareTest>'

  2/2: [=============================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.07189s

求怎么破?谢谢!

贴代码。

#1 楼 @rei 已贴,谢谢!

save! 在校验不通过的时候是抛异常的,要不抛异常用 save,这时候要根据返回值处理:

if @hardware.save
  # save success
else
  # save fail
end

验证条件:

validates :AssetNum, presence: true  # nil 或空字符串都会失败; 

测试为:

AssetNum: "" ,

这个能不报错吗?另外建议用 factorygirl 来写测试的配置,

#4 楼 @flingfox63 感谢答复,约束的目的就是不允许为空或 nil,所以不能 allow_blank。而我测试的目的也是验证提交了空值是否能创建成功。我预期的是所有测试都能通过,而现在因为非空约束导致测试中出现 error。感谢指出的 factorygirl,我去学习一下,谢谢!

#3 楼 @rei 我还是先偷懒 save 吧,等应用上线了我再慢慢优化。谢谢!

我的回答有点远了,请忽略......@rei 改成 save 是正解

#7 楼 @flingfox63 不远,很有价值,谢谢!

save 和 save! 是有区别的,save! 本身就是要抛出错误信息的,save 返回 true 或者 false

#9 楼 @zouchaoge 了解,问题不是数据库的约束,而是 controller 的方法中,谢谢!

11 楼 已删除
需要 登录 后方可回复, 如果你还没有账号请 注册新账号