集成测试跨越多个控制器和操作,将它们全部连接在一起,以确保它们按预期一起工作。与单元测试或功能测试相比,它更完整地进行测试,从调度程序到数据库,对整个堆栈进行测试。
最简单的方法是扩展 IntegrationTest
并使用 Integration::RequestHelpers#get
和/或 Integration::RequestHelpers#post
方法编写测试。
require "test_helper"
class ExampleTest < ActionDispatch::IntegrationTest
fixtures :people
def test_login
# get the login page
get "/login"
assert_equal 200, status
# post the login and follow through to the home page
post "/login", params: { username: people(:jamis).username,
password: people(:jamis).password }
follow_redirect!
assert_equal 200, status
assert_equal "/home", path
end
end
但是,您也可以在每个测试中打开多个会话实例,甚至使用断言和方法扩展这些实例,以创建针对您的应用程序的非常强大的测试 DSL。
require "test_helper"
class AdvancedTest < ActionDispatch::IntegrationTest
fixtures :people, :rooms
def test_login_and_speak
jamis, david = login(:jamis), login(:david)
room = rooms(:office)
jamis.enter(room)
jamis.speak(room, "anybody home?")
david.enter(room)
david.speak(room, "hello!")
end
private
module CustomAssertions
def enter(room)
# reference a named route, for maximum internal consistency!
get(room_url(id: room.id))
assert(...)
...
end
def speak(room, message)
post "/say/#{room.id}", xhr: true, params: { message: message }
assert(...)
...
end
end
def login(who)
open_session do |sess|
sess.extend(CustomAssertions)
who = people(who)
sess.post "/login", params: { username: who.username,
password: who.password }
assert(...)
end
end
end
另一个更长的示例将是
一个简单的集成测试,它练习多个控制器
require "test_helper"
class UserFlowsTest < ActionDispatch::IntegrationTest
test "login and browse site" do
# login via https
https!
get "/login"
assert_response :success
post "/login", params: { username: users(:david).username, password: users(:david).password }
follow_redirect!
assert_equal '/welcome', path
assert_equal 'Welcome david!', flash[:notice]
https!(false)
get "/articles/all"
assert_response :success
assert_select 'h1', 'Articles'
end
end
如您所见,集成测试涉及多个控制器,并从数据库到调度程序对整个堆栈进行测试。此外,您可以在测试中同时打开多个会话实例,并使用断言方法扩展这些实例,以专门为您的应用程序创建非常强大的测试 DSL(特定于域的语言)。
以下是集成测试中多个会话和自定义 DSL 的示例
require "test_helper"
class UserFlowsTest < ActionDispatch::IntegrationTest
test "login and browse site" do
# User david logs in
david = login(:david)
# User guest logs in
guest = login(:guest)
# Both are now available in different sessions
assert_equal 'Welcome david!', david.flash[:notice]
assert_equal 'Welcome guest!', guest.flash[:notice]
# User david can browse site
david.browses_site
# User guest can browse site as well
guest.browses_site
# Continue with other assertions
end
private
module CustomDsl
def browses_site
get "/products/all"
assert_response :success
assert_select 'h1', 'Products'
end
end
def login(user)
open_session do |sess|
sess.extend(CustomDsl)
u = users(user)
sess.https!
sess.post "/login", params: { username: u.username, password: u.password }
assert_equal '/welcome', sess.path
sess.https!(false)
end
end
end
有关如何使用 get
等的帮助,请参阅 [请求帮助程序文档] (ActionDispatch::Integration::RequestHelpers)。
更改请求编码
您还可以通过设置请求应编码的方式来轻松测试您的 JSON API
require "test_helper"
class ApiTest < ActionDispatch::IntegrationTest
test "creates articles" do
assert_difference -> { Article.count } do
post articles_path, params: { article: { title: "Ahoy!" } }, as: :json
end
assert_response :success
assert_equal({ id: Article.last.id, title: "Ahoy!" }, response.parsed_body)
end
end
as
选项传递一个“application/json” Accept 标头(从而将请求格式设置为 JSON,除非被覆盖),将内容类型设置为“application/json” 并将参数编码为 JSON。
在响应上调用 TestResponse#parsed_body
会根据最后一个响应 MIME 类型解析响应主体。
开箱即用,只支持 :json
。但是,对于您注册的任何自定义 MIME 类型,您可以使用以下方法添加自己的编码器:
ActionDispatch::IntegrationTest.register_encoder :wibble,
param_encoder: -> params { params.to_wibble },
response_parser: -> body { body }
其中 param_encoder
定义了如何编码参数,response_parser
定义了如何通过 TestResponse#parsed_body
解析响应主体。
有关更多信息,请参阅 Rails 测试指南。