Rails 7启用Turbo后Minitest的assert_difference失效问题
Turbo启用后Rails系统测试邮件断言失败的原因与修复方法
问题原因
Turbo 默认通过异步 AJAX 请求处理带有 data-turbo="true" 的链接,系统测试里的 click_link 方法执行后会立刻继续后续代码,不会等待 Turbo 完成后端请求和页面更新。而 assert_difference 块在 click_link 执行完毕后就会检查邮件计数,这时候后端还没来得及发送邮件,导致断言失败。
在未启用 Turbo 时,链接是同步请求,click_link 会等待页面完全加载后才继续,所以断言能正确捕获邮件发送的计数变化。
修复方案
方案1:等待页面状态更新(推荐)
在 click_link 后添加等待逻辑,确保后端请求完成后再结束断言块。比如等待页面出现审批完成的标识元素:
test 'welcome email gets sent on new user approval' do # ... 前置代码 assert_difference('ActionMailer::Base.deliveries.count', 1) do click_link("super_admin_approves_user_#{user.id}") # 等待页面显示审批完成的状态文本或元素 expect(page).to have_content('用户已审批') end # ... 后续断言 end
方案2:强制链接使用同步请求
修改视图中的链接,添加 data-turbo="false" 禁用 Turbo 异步处理,让请求回到传统的同步模式:
<%= link_to '审批用户', super_admin_approves_user_path(user), id: "super_admin_approves_user_#{user.id}", data: { turbo: false } %>
这个方法无需修改测试代码,但会失去 Turbo 带来的无刷新体验,适合快速临时修复。
方案3:使用Turbo测试辅助方法等待导航
如果你的测试环境加载了 Turbo 的测试辅助工具,可以直接调用 turbo.wait_for_navigation 等待异步请求完成:
test 'welcome email gets sent on new user approval' do # ... 前置代码 assert_difference('ActionMailer::Base.deliveries.count', 1) do click_link("super_admin_approves_user_#{user.id}") turbo.wait_for_navigation end # ... 后续断言 end
内容的提问来源于stack exchange,提问作者Darme
相关产品推荐
相关产品推荐

