Rails 7 系统测试由于模型回调而出现错误,我该如何解决这个问题?

Rails 7 system tests gives an error because of model callback, how can i fix this?

提问人:Sercan Tırnavalı 提问时间:4/20/2022 更新时间:4/20/2022 访问量:277

问:

我正在尝试测试我的表单行为,但是当我单击保存时,回调会抛出如下所示的错误。 如果我评论下面的代码,一切正常。在这里,我不想测试回调,但它阻止了我成功测试行为。

我能做些什么来解决这个问题。

#before_create :assign_depth
#before_save   :assign_depth

fond.yml |夹具

first:
  name: At vero eos et accusamus
  explanation: some explanation
  parent: 
second:
  name: laborum et dolorum fuga. Et
  explanation: some explanation
  parent: first

fond.rb 模型

class Fond < ApplicationRecord
    ...
  before_create :assign_depth
  before_save   :assign_depth
  
  belongs_to :parent, class_name: "Fond", optional: true
  has_many :children, class_name: "Fond", foreign_key: "parent_id", dependent: :nullify

  private
    def assign_depth
      self.depth = (self.parent.present? ? parent.depth + 1 : 0)
    end
end

测试

require "application_system_test_case"

class FondsTest < ApplicationSystemTestCase
  setup do
    login_as users(:admin)
    @fond_related = fonds(:second)
  end

  test "should create related fond" do
    visit fonds_url
    click_on "New fond"

    fill_in "Name", with: "Test Test Test"
    fill_in "Explanation", with: @fond_related.explanation
    first(:xpath, "/html/body/div[2]/div[2]/form/div[3]/div").click()
    
    find('div.item', text: @fond_related.name).click()

    click_on ("Fond Kaydet")

    assert_text "Fond was successfully created"
  end
end

测试结果

E

Error:
FondsTest#test_should_create_related_fond:
NoMethodError: undefined method `+' for nil:NilClass
    app/models/fond.rb:29:in `assign_depth'
    app/controllers/fonds_controller.rb:29:in `block in create'
    app/controllers/fonds_controller.rb:28:in `create'
Ruby-on-Rails 测试 回调

评论


答:

1赞 Alex 4/20/2022 #1

在回调中,您正在检查是否存在,但现在和现在都很糟糕。系统测试是一个完整的堆栈测试,这里没有跳过(如果我是这里的管理员,我现在正在查看错误 500)。parentparent.depthnilnil+1

您的测试正在执行它应该做的事情,检查行为并查找错误。你已经成功找到了一个。您应该在数据库中将默认值设置为 0,这样它永远不会返回 nil。迁移应如下所示:depthnull: false

def change
  create_table :fonds do |t|
    t.integer :depth, default: 0, null: false
  end
end

更改现有列

def change
  change_column_default(:fonds, :depth, from: nil, to: 0)
  change_column_null(:fonds, :depth, false)
end

任何低于此值的指标都意味着您每次想要操作它时都必须检查深度。此外,还应在模型中进行验证Fond

validates :depth, presence: true, numericality: true