Skip to content

Instantly share code, notes, and snippets.

@davegurnell
Created January 27, 2017 10:15
Show Gist options
  • Select an option

  • Save davegurnell/8278fe7c803f81596b5ab2f6a8a4f024 to your computer and use it in GitHub Desktop.

Select an option

Save davegurnell/8278fe7c803f81596b5ab2f6a8a4f024 to your computer and use it in GitHub Desktop.
Rough Play manual DI example. Note I haven't compiled this, so it's probably full of typos and broken imports.
package startup
import controllers._
import services._
import akka.actor.ActorSystem
import play.api.ApplicationLoader.Context
import play.api.libs.ws.ahc._
import play.api.routing.Router
import play.api._
import play.api.mvc.EssentialFilter
import router.Routes
trait ApplicationComponents extends AhcWSComponents {
self: BuiltInComponents =>
// Note: We're extending AhcWsComponents
// to get a preconfigured `wsClient`
// Create modules for the application
// (these are all examples)...
lazy val fooService: FooService = new FooService(configuration, wsClient)
lazy val barService: BarService = new BarService(configuration, wsClient)
// Create controllers based on application modules
// (again, these are examples)
lazy val fooController: FooController = new FooController(fooService)
lazy val barController: BarController = new BarController(barService)
// Define a router and override default modules if required...
override lazy val httpFilters: Seq[EssentialFilter] = // etc...
override lazy val httpErrorHandler: ErrorHandler = // etc...
override lazy val httpRequestHandler: RequestHandler = // etc...
// `router` is the only abstract member from `BuiltInComponentsWithContext`.
// `_root_.router.Routes` is created by the Play routes file.
// The order of parameters depends on the order routes are encountered in the file.
lazy val router: Router = new Routes(
httpErrorHandler,
fooController,
barController,
prefix = ""
)
}
package startup
import play.api.{ApplicationLoader => PlayApplicationLoader}
import play.api.ApplicationLoader.Context
class ApplicationLoader extends PlayApplicationLoader {
def load(context: Context) =
new StartupModule(context).application
}
import play.api._
import play.api.libs.concurrent.Execution.Implicits._
import play.api.libs.json._
import play.api.test._
class ExampleSpec extends Specification {
"an example test" should {
"use mocked out services" in new MockedComponents {
// fooService and barService are mocked out here,
// and fooController, barController and the application
// are all redefined to use them
}
}
}
package startup
import org.specs2.execute.{AsResult, Result}
import org.specs2.matcher._
import org.specs2.mutable._
import play.api.{ApplicationLoader, BuiltInComponents, Mode}
import play.api.test._
import play.api.Environment, Configuration}
trait TestComponents extends Scope with Around with BuiltInComponents with ApplicationComponents {
// This is a trait that we can wrap around Specs2 tests
// to instantiate the application and mock out certain components.
//
// There will be a close equivalent for Scalatest.
//
// There's not necessarily any fancy mocking framework here...
// we simply override the `lazy vals` for the services we want to swap out.
lazy val context = {
val classLoader = ApplicationLoader.getClass.getClassLoader
val env = new Environment(new java.io.File("."), classLoader, Mode.Test)
ApplicationLoader.createContext(env)
}
override lazy val fooService = MockFooService(/* ... */)
override lazy val barService = MockBarService(/* ... */)
implicit lazy val app = application
def around[A](body: => A)(implicit ev: AsResult[A]): Result =
Helpers.running(app)(ev.asResult(body))
}
GET /foo controllers.FooController.index
GET /bar controllers.BarController.index
package startup
import play.api.ApplicationLoader.Context
import play.api.BuiltInComponentsFromContext
class StartupModule(context: Context)
extends BuiltInComponentsFromContext(context)
with ApplicationComponents {
// Do things on boot...
// (all dependencies are in scope)
Logger.info("It lives!")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment