/core/play-guice/src/test/scala/play/api/inject/guice/GuiceApplicationBuilderSpec.scala

https://github.com/playframework/playframework · Scala · 213 lines · 174 code · 36 blank · 3 comment · 0 complexity · 68374a311c03866ba56a7affff6d3662 MD5 · raw file

  1. /*
  2. * Copyright (C) Lightbend Inc. <https://www.lightbend.com>
  3. */
  4. package play.api.inject
  5. package guice
  6. import java.util.Collections
  7. import com.google.inject.CreationException
  8. import com.google.inject.Guice
  9. import com.google.inject.ProvisionException
  10. import com.typesafe.config.Config
  11. import javax.inject.Inject
  12. import javax.inject.Provider
  13. import javax.inject.Singleton
  14. import org.specs2.mutable.Specification
  15. import play.api.Configuration
  16. import play.api.i18n.I18nModule
  17. import play.api.mvc.CookiesModule
  18. import play.core.WebCommands
  19. import play.inject.{ Module => JavaModule }
  20. import play.{ Environment => JavaEnvironment }
  21. class GuiceApplicationBuilderSpec extends Specification {
  22. "GuiceApplicationBuilder" should {
  23. "add bindings with Scala" in {
  24. addBindings(new GuiceApplicationBuilderSpec.AModule)
  25. }
  26. "add bindings with Java" in {
  27. addBindings(new GuiceApplicationBuilderSpec.JavaAModule)
  28. }
  29. def addBindings(module: Module) = {
  30. val injector = new GuiceApplicationBuilder()
  31. .bindings(module, bind[GuiceApplicationBuilderSpec.B].to[GuiceApplicationBuilderSpec.B1])
  32. .injector()
  33. injector.instanceOf[GuiceApplicationBuilderSpec.A] must beAnInstanceOf[GuiceApplicationBuilderSpec.A1]
  34. injector.instanceOf[GuiceApplicationBuilderSpec.B] must beAnInstanceOf[GuiceApplicationBuilderSpec.B1]
  35. }
  36. "override bindings with Scala" in {
  37. overrideBindings(new GuiceApplicationBuilderSpec.AModule)
  38. }
  39. "override bindings with Java" in {
  40. overrideBindings(new GuiceApplicationBuilderSpec.JavaAModule)
  41. }
  42. def overrideBindings(module: Module) = {
  43. val app = new GuiceApplicationBuilder()
  44. .bindings(module)
  45. .overrides(
  46. bind[Configuration] to new GuiceApplicationBuilderSpec.ExtendConfiguration("a" -> 1),
  47. bind[GuiceApplicationBuilderSpec.A].to[GuiceApplicationBuilderSpec.A2]
  48. )
  49. .build()
  50. app.configuration.get[Int]("a") must_== 1
  51. app.injector.instanceOf[GuiceApplicationBuilderSpec.A] must beAnInstanceOf[GuiceApplicationBuilderSpec.A2]
  52. }
  53. "disable modules with Scala" in {
  54. disableModules(new GuiceApplicationBuilderSpec.AModule)
  55. }
  56. "disable modules with Java" in {
  57. disableModules(new GuiceApplicationBuilderSpec.JavaAModule)
  58. }
  59. def disableModules(module: Module) = {
  60. val injector = new GuiceApplicationBuilder()
  61. .bindings(module)
  62. .disable(module.getClass)
  63. .injector()
  64. injector.instanceOf[GuiceApplicationBuilderSpec.A] must throwA[com.google.inject.ConfigurationException]
  65. }
  66. "set initial configuration loader" in {
  67. val extraConfig = Configuration("a" -> 1)
  68. val app = new GuiceApplicationBuilder()
  69. .loadConfig(env => extraConfig.withFallback(Configuration.load(env)))
  70. .build()
  71. app.configuration.get[Int]("a") must_== 1
  72. }
  73. "set module loader" in {
  74. val injector = new GuiceApplicationBuilder()
  75. .load((env, conf) =>
  76. Seq(
  77. new BuiltinModule,
  78. new I18nModule,
  79. new CookiesModule,
  80. bind[GuiceApplicationBuilderSpec.A].to[GuiceApplicationBuilderSpec.A1]
  81. )
  82. )
  83. .injector()
  84. injector.instanceOf[GuiceApplicationBuilderSpec.A] must beAnInstanceOf[GuiceApplicationBuilderSpec.A1]
  85. }
  86. "set loaded modules directly" in {
  87. val injector = new GuiceApplicationBuilder()
  88. .load(
  89. new BuiltinModule,
  90. new I18nModule,
  91. new CookiesModule,
  92. bind[GuiceApplicationBuilderSpec.A].to[GuiceApplicationBuilderSpec.A1]
  93. )
  94. .injector()
  95. injector.instanceOf[GuiceApplicationBuilderSpec.A] must beAnInstanceOf[GuiceApplicationBuilderSpec.A1]
  96. }
  97. "eagerly load singletons" in {
  98. new GuiceApplicationBuilder()
  99. .load(
  100. new BuiltinModule,
  101. new I18nModule,
  102. new CookiesModule,
  103. bind[GuiceApplicationBuilderSpec.C].to[GuiceApplicationBuilderSpec.C1]
  104. )
  105. .eagerlyLoaded()
  106. .injector() must throwA[CreationException]
  107. }
  108. "work with built in modules and requireAtInjectOnConstructors" in {
  109. new GuiceApplicationBuilder()
  110. .load(new BuiltinModule, new I18nModule, new CookiesModule)
  111. .requireAtInjectOnConstructors()
  112. .eagerlyLoaded()
  113. .injector() must not(throwA[CreationException])
  114. }
  115. "set lazy load singletons" in {
  116. val builder = new GuiceApplicationBuilder()
  117. .load(
  118. new BuiltinModule,
  119. new I18nModule,
  120. new CookiesModule,
  121. bind[GuiceApplicationBuilderSpec.C].to[GuiceApplicationBuilderSpec.C1]
  122. )
  123. builder.injector() must throwAn[CreationException].not
  124. builder.injector().instanceOf[GuiceApplicationBuilderSpec.C] must throwAn[ProvisionException]
  125. }
  126. "bind a unique singleton instance of WebCommands" in {
  127. val applicationModule = new GuiceApplicationBuilder()
  128. .load(new BuiltinModule, new I18nModule, new CookiesModule)
  129. .applicationModule()
  130. val injector1 = Guice.createInjector(applicationModule)
  131. val injector2 = Guice.createInjector(applicationModule)
  132. injector1.getInstance(classOf[WebCommands]) must_=== injector1.getInstance(classOf[WebCommands])
  133. injector2.getInstance(classOf[WebCommands]) must_!== injector1.getInstance(classOf[WebCommands])
  134. }
  135. "display logger deprecation message" in {
  136. List("logger", "logger.resource", "logger.resource.test").forall { path =>
  137. List("DEBUG", "WARN", "INFO", "ERROR", "TRACE", "OFF").forall { value =>
  138. val data = Map(path -> value)
  139. val builder = new GuiceApplicationBuilder()
  140. builder.shouldDisplayLoggerDeprecationMessage(Configuration.from(data)) must_=== true
  141. }
  142. }
  143. }
  144. "not display logger deprecation message" in {
  145. List("logger", "logger.resource", "logger.resource.test").forall { path =>
  146. val data = Map(path -> "NOT_A_DEPRECATED_VALUE")
  147. val builder = new GuiceApplicationBuilder()
  148. builder.shouldDisplayLoggerDeprecationMessage(Configuration.from(data)) must_=== false
  149. }
  150. }
  151. }
  152. }
  153. object GuiceApplicationBuilderSpec {
  154. class ExtendConfiguration(conf: (String, Any)*) extends Provider[Configuration] {
  155. @Inject
  156. var injector: Injector = _
  157. lazy val get = {
  158. Configuration.from(conf.toMap).withFallback(injector.instanceOf[ConfigurationProvider].get)
  159. }
  160. }
  161. trait A
  162. class A1 extends A
  163. class A2 extends A
  164. class AModule extends SimpleModule(bind[A].to[A1])
  165. trait B
  166. class B1 extends B
  167. trait C
  168. @Singleton
  169. class C1 extends C {
  170. throw new EagerlyLoadedException
  171. }
  172. class JavaAModule extends JavaModule {
  173. override def bindings(environment: JavaEnvironment, config: Config) =
  174. Collections.singletonList(JavaModule.bindClass(classOf[A]).to(classOf[A1]))
  175. }
  176. class EagerlyLoadedException extends RuntimeException
  177. }