上集聚焦單元測試與模型層驗證,本文深入 Rails 功能測試(控制器+視圖)與集成測試(跨控制器流程),展示集成框架如何將測試從「孤立單元」延伸至「端到端業務場景」。
Rails 自動生成的 test/functional/trails_controller_test.rb 直接發送 HTTP 請求:
def test_list
get :list # 模擬 GET /trails/list
assert_response :success # HTTP 200
assert_template 'list' # 渲染 list 模板
assert_not_nil assigns(:trails) # @trails 實例變量已賦值
end
def test_create
num_trails = Trail.count
post :create, trail: { # 模擬 POST /trails/create
name: "Hermosa Creek",
description: "Lots of altitude, all down",
difficulty: "Medium"
}
assert_response :redirect # HTTP 302 重定向
assert_redirected_to action: 'list' # 重定向目標正確
assert_equal num_trails + 1, Trail.count # 數據庫確實新增
end
關鍵點:
get/post/put/delete 直接調用控制器動作,繞過 Web 服務器,速度極快。assigns(:trails) 訪問控制器實例變量 @trails,白盒驗證視圖數據準備。Rails 1.1+ 引入 ActionController::IntegrationTest,支持會話級多請求串聯:
require 'test_helper'
class DestroyAndShowTest < ActionController::IntegrationTest
fixtures :trails
def test_multiple_actions
# 1. 訪問列表頁
get "/trails/list"
assert_response :success
# 2. 刪除第一條記錄
post "/trails/destroy/1"
assert_response :redirect
assert_nil response.body =~ /Emma Long/ # 頁面不再包含已刪除記錄
assert_equal 2, Trail.count # 數據庫驗證
# 3. 跟隨重定向並驗證列表更新
follow_redirect!
assert_response :success
# 4. 訪問第二條記錄詳情
get "/trails/show/2"
assert_response :success
end
end
核心能力:
script/console 中直接 app.get('/trails/list')、app.response.body 即時調試,隨手轉化為自動化測試用例。
class Date
def self.today
Date.civil(2006, 2, 2) # 固定為土撥鼠日
end
end
直接「猴子補丁」核心類 Date,測試期間全局生效,無需依賴注入框架、無需 Mock 框架、無需修改生產代碼。Java 中需引入 PowerMock/JMockit 或重構為可注入 Clock 介面。
fixtures/trails.yml 聲明測試數據,可引用標籤 trails(:emma_long)。DELETE + INSERT。| 能力 | Rails | Java 對標方案 |
|---|---|---|
| 功能測試 | 控制器測試 + assigns 白盒驗證 | Spring MVC Test (MockMvc) + @WebMvcTest |
| 集成測試 | IntegrationTest + 會話 + follow_redirect | Spring Boot @SpringBootTest + TestRestTemplate / WebTestClient |
| 測試數據管理 | Fixture + 事務回滾 | @Sql + @Transactional + TestContainers |
| 運行時存根 | 開放類猴子補丁 | Mockito/PowerMock / 介面抽象 + @MockBean |
| 探索式測試 | Console 即時交互 | Groovy Shell / JShell / Spring Boot DevTools |
@Sql 或 Flyway/Liquibase 初始化公共數據,各測試類在事務中隔離變更。Rails 測試體系的精髓在於框架級約定消除樣板、動態語言特性賦能表達、統一 API 橫貫測試金字塔。Java 雖難完全複製其動態魔法,但通過 Spring Boot Test、MockMvc、TestContainers、Groovy/JShell 等現代工具鏈,完全能構建出同樣高效、可維護、分層清晰的測試體系。測試不僅是質量保障,更是設計質量的試金石——難以測試的代碼,往往就是糟糕的設計。