You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Minitest测试before_destroy回调并传入selected_store_id?

问题描述

昨天我询问了如何用Minitest测试私有方法,得到了不应测试私有方法的建议,于是把逻辑从控制器移到了Store模型,代码如下:

class Store < ApplicationRecord
  attr_accessor :selected_store_id
  
  before_destroy :move_employees_to_selected_store
  
  scope :by_name, -> { order(name: :asc) }

  belongs_to :organization
  has_many :employments

  validates_presence_of :name

  def move_employees_to_selected_store
    return unless selected_store_id.present?
    store = organization.store.find(selected_store_id)
    employments.update_all(store_id: store.id)
  end
end

这段逻辑在实际运行中是正常的(selected_store_id会在视图中更新),但测试时没办法传入selected_store_id,我写的测试用例如下:

def test_employments_are_moved_to_selected_store_when_store_is_removed
  u = UserFactory.create
  o = OrganizationFactory.create
  s1 = o.store.create(name: "Test")
  s2 = o.store.create(name: "Test 2")
  s1.employments.create(user: u)
  s1.destroy
  assert_equal s2.employments.count, 1
end

断言无法通过,请问该如何重构测试或回调来传入门店ID?


解决方案

方法一:直接在测试中设置selected_store_id

既然selected_store_id是用attr_accessor定义的实例变量,测试时直接给s1赋值即可:

def test_employments_are_moved_to_selected_store_when_store_is_removed
  u = UserFactory.create
  o = OrganizationFactory.create
  s1 = o.store.create(name: "Test")
  s2 = o.store.create(name: "Test 2")
  s1.employments.create(user: u)
  
  # 直接指定目标门店ID
  s1.selected_store_id = s2.id
  s1.destroy
  
  assert_equal s2.employments.count, 1
end

这样回调执行时就能拿到selected_store_id,完成员工转移,断言即可通过。

方法二:优化回调逻辑(可选)

如果觉得依赖实例变量不够直观,可以给模型新增带参数的销毁方法,明确转移目标:

# Store模型新增方法
def destroy_with_transfer(target_store_id)
  self.selected_store_id = target_store_id
  destroy
end

测试时调用这个方法:

def test_employments_are_moved_to_selected_store_when_store_is_removed
  u = UserFactory.create
  o = OrganizationFactory.create
  s1 = o.store.create(name: "Test")
  s2 = o.store.create(name: "Test 2")
  s1.employments.create(user: u)
  
  s1.destroy_with_transfer(s2.id)
  
  assert_equal s2.employments.count, 1
end

另外注意:模型中organization.store.find应该修正为organization.stores.find(has_many关联对应复数形式),避免实际运行时出现错误。


内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 09:55:27