§使用编译时依赖注入进行测试
如果您正在手动连接应用程序或使用 编译时依赖注入,那么您可以直接使用和自定义应用程序组件,或者创建特定于测试用例的测试变体。您还可以修改和覆盖过滤器、定义路由以及指定配置。
§BuiltInComponentsFromContext
BuiltInComponentsFromContext 为我们提供了一种轻松引导组件的方法。在给定上下文的情况下,它提供了所有必需的内置组件:environment
、configuration
、applicationLifecycle
等。
如 编译时依赖注入 中所述,这是手动连接应用程序最常见的方式。
在测试时,我们可以使用真实组件,这使我们能够启动完整的应用程序以进行完整的功能测试,或者我们可以创建测试组件,这些组件根据需要启动应用程序的子集。
§WithApplicationComponents
测试组件的关键是 WithApplicationComponents 特征。它设置了应用程序、服务器和上下文,准备进行测试。根据您的测试策略,可以使用许多可供混合的子特征
。
* OneAppPerSuiteWithComponents
* OneAppPerTestWithComponents
* OneServerPerSuiteWithComponents
* OneServerPerTestWithComponents
建议您熟悉每个特征
的文档,以便决定哪个最适合您的需求。
§在代码中定义组件
如上所述,可以在测试中直接定义组件。为此,只需覆盖组件并完成 BuiltInComponentsFromContext 的实现,并提供路由器。
override def components: BuiltInComponents = new BuiltInComponentsFromContext(context) with NoHttpFiltersComponents {
import play.api.mvc.Results
import play.api.routing.Router
import play.api.routing.sird._
lazy val router: Router = Router.from({
case GET(p"/") =>
defaultActionBuilder {
Results.Ok("success!")
}
})
override lazy val configuration: Configuration =
Configuration("foo" -> "bar", "ehcacheplugin" -> "disabled").withFallback(context.initialConfiguration)
}
上面
* 我们在实现中定义了导入,以防止在断言动词时sird
和play.api.http
包之间发生冲突。
* 我们定义了一个测试路由器并实现了相应的路由,在本例中,我们匹配根补丁。
* 我们覆盖了配置以提供要在测试中使用的附加值,这当然可选。
§使用现有组件
如果我们想使用现有的应用程序组件,我们只需在测试中实例化它们。
override def components: BuiltInComponents = new SomeAppComponents(context)
此外,还可以覆盖组件
中的任何定义,以提供额外的配置或模拟数据库等。
override def components: BuiltInComponents = new SomeAppComponents(context) {
override lazy val configuration: Configuration =
Configuration("ehcacheplugin" -> "enabled").withFallback(context.initialConfiguration)
}
§完整示例
class ExampleComponentsSpec extends PlaySpec with OneAppPerSuiteWithComponents {
// #scalacomponentstest-inlinecomponents
override def components: BuiltInComponents = new BuiltInComponentsFromContext(context) with NoHttpFiltersComponents {
import play.api.mvc.Results
import play.api.routing.Router
import play.api.routing.sird._
lazy val router: Router = Router.from({
case GET(p"/") =>
defaultActionBuilder {
Results.Ok("success!")
}
})
override lazy val configuration: Configuration =
Configuration("foo" -> "bar", "ehcacheplugin" -> "disabled").withFallback(context.initialConfiguration)
}
// #scalacomponentstest-inlinecomponents
"The OneAppPerSuiteWithComponents trait" must {
"provide an Application" in {
import play.api.test.Helpers.GET
import play.api.test.Helpers.route
val Some(result: Future[Result]) = route(app, FakeRequest(GET, "/"))
Helpers.contentAsString(result) must be("success!")
}
"override the configuration" in {
app.configuration.getOptional[String]("foo") mustBe Some("bar")
}
}
}
§嵌套规范
如果您有许多可以共享相同应用程序
的测试,并且不想将它们全部放在一个测试类中,可以将它们放在不同的套件
类中。这些将是您的嵌套套件。创建一个扩展适当特征
的主套件,例如OneAppPerSuiteWithComponents
,并声明嵌套套件
。最后,使用@DoNotDiscover
注释嵌套套件,并让它们扩展ConfiguredApp
。以下是一个示例
class NestedExampleSpec
extends Suites(new OneSpec, new TwoSpec, new RedSpec, new BlueSpec)
with OneAppPerSuiteWithComponents
with TestSuite {
override def components: BuiltInComponents = new BuiltInComponentsFromContext(context) with NoHttpFiltersComponents {
import play.api.mvc.Results
import play.api.routing.Router
import play.api.routing.sird._
lazy val router: Router = Router.from({
case GET(p"/") =>
defaultActionBuilder {
Results.Ok("success!")
}
})
override lazy val configuration: Configuration =
Configuration("ehcacheplugin" -> "disabled").withFallback(context.initialConfiguration)
}
}
// These are the nested suites
@DoNotDiscover class OneSpec extends PlaySpec with ConfiguredApp {
"OneSpec" must {
"make the Application available implicitly" in {
def getConfig(key: String)(implicit app: Application) = app.configuration.getOptional[String](key)
getConfig("ehcacheplugin") mustBe Some("disabled")
}
}
}
@DoNotDiscover class TwoSpec extends PlaySpec with ConfiguredApp
@DoNotDiscover class RedSpec extends PlaySpec with ConfiguredApp
@DoNotDiscover class BlueSpec extends PlaySpec with ConfiguredApp {
"The NestedExampleSpec" must {
"provide an Application" in {
import play.api.test.Helpers.GET
import play.api.test.Helpers.route
val Some(result: Future[Result]) = route(app, FakeRequest(GET, "/"))
Helpers.contentAsString(result) must be("success!")
}
}
}
下一步: 使用数据库进行测试
发现文档中的错误?此页面的源代码可以在 这里 找到。阅读完 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?前往 我们的社区论坛 与社区开始对话。