控制器通常必須與其它元件互動,例如模型,所以在Rails後,會假設控制器測試是功能測試,你產生一個控制器,就會有相對應的測試檔案放置在test/functional中。例如 觀摩 Scaffold 中產生了messages_controller.rb,就產生了對應的test/functional/messages_controller_test.rb,可觀摩其中如何對控制器進行測試:
- messages_controller_test.rb
class MessagesControllerTest < ActionController::TestCase
setup do
@message = messages(:one)
end
test "should get index" do
# GET請求index動作
get :index
# 斷言200成功回應
assert_response :success
# 斷言控制器設定了messages實例變數
assert_not_nil assigns(:messages)
end
test "should get new" do
get :new
assert_response :success
end
test "should create message" do
# 在程式區塊執行完畢後,Message對應表格的資料筆數一定會多一筆
assert_difference('Message.count') do
# POST請求create動作,params[:message]就是@message.attributes
post :create, message: @message.attributes
end
# 斷言設定了message實例變數並重導至messages/:id
assert_redirected_to message_path(assigns(:message))
end
test "should show message" do
# GET請求show動作,id請求參數設為@message.to_param
get :show, id: @message.to_param
assert_response :success
end
test "should get edit" do
get :edit, id: @message.to_param
assert_response :success
end
test "should update message" do
# PUT請求update動作
put :update, id: @message.to_param, message: @message.attributes
assert_redirected_to message_path(assigns(:message))
end
test "should destroy message" do
# 在程式區塊執行完畢後,Message對應表格的資料筆數一定會少一筆
assert_difference('Message.count', -1) do
# DELETE請求destroy動作
delete :destroy, id: @message.to_param
end
assert_redirected_to messages_path
end
end
Rails在控制器測試時,提供了幾個請求方法:
- get
- post
- put
- head
- delete
實際上控制器測試時,並不會區別這幾個方法的差別,只是為了在測試時更具語意而已,這幾個方法會發出請求,呼叫時可依序接受四個參數:
- 以Symbol或字串指定要請求的動作
- 選擇性以Hash指定請求參數
- 選擇性以Hash指定session資料
- 選擇性以Hash指定flash資料
例如想請求show動作,請求參數id為1,而session中user_id設為5,可如下呼叫:
get(:show, {'id' => "12"}, {'user_id' => 5})
例如想請求view動作,請求參數id為12,不設餐session,但設定flash中message為booya:
get(:view, {'id' => '12'}, nil, {'message' => 'booya!'})
在請求被控制器的相關動作處理之後,可以使用以下幾個方法取得控制器中設定的資料:
- assign:取得控制器中設定的實例變數
- cookies:取得cookies傳回物件
- session:取得session傳回物件
- flash:取得flash傳回物件
除此之外,還可以使用以下幾個變數,取得控制器中的三個實例變數:
- @controller
- @request
- @response
@request.cookies[:user] = "caterpillar"