Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Play application integration tests with guice context

I'm new to play framework and have limited experience with scala. Using play framework 2.4 I'm trying to write full integrations tests where I want to call controller, and using in-memory db retrieve data from it. I'm using scalatest-plus together with scalatest. I have read about play unit tests in play documentation and now trying to use play.api.test.FakeApplication but i cannot find a way to inject my guice module to this fake application. I'm ussing OneAppPerSuite trait I can override FakeApplication but cannot pass any guice module for injection. Here is FakeApplication source from:

case class FakeApplication(
  override val path: java.io.File = new java.io.File("."),
  override val classloader: ClassLoader = classOf[FakeApplication].getClassLoader,
  additionalPlugins: Seq[String] = Nil,
  withoutPlugins: Seq[String] = Nil,
  additionalConfiguration: Map[String, _ <: Any] = Map.empty,
  withGlobal: Option[play.api.GlobalSettings] = None,
  withRoutes: PartialFunction[(String, String), Handler] = PartialFunction.empty) extends Application {

private val app: Application = new GuiceApplicationBuilder()
  .in(Environment(path, classloader, Mode.Test))
  .global(withGlobal.orNull)
  .configure(additionalConfiguration)
  .bindings(
    bind[FakePluginsConfig] to FakePluginsConfig(additionalPlugins, withoutPlugins),
    bind[FakeRouterConfig] to FakeRouterConfig(withRoutes))
  .overrides(
    bind[Plugins].toProvider[FakePluginsProvider],
    bind[Router].toProvider[FakeRouterProvider])
  .build

  ....

So there is no way for me to pass custom module here.

Here is how my test looks like:

class UsersControllerTest extends PlaySpec with OneAppPerSuite {

    override implicit lazy val app = FakeApplication(additionalConfiguration = inMemoryDatabase())

    "Application " should {

       "work" in {
         val resp = route(FakeRequest(GET, "/api/users")).get
        }
    }

}

And here is my controller I want to test:

class UserController @Inject()
  (userService: UserService)
  (implicit ec: ExecutionContext) extends Controller {

  def get = Action.async { implicit request => {
    // implementation
    }
  }

}

Obviously my test now fail since it cannot find UserService instance. So my question is:

  1. How to properly write end2end integration tests with play using guice context
  2. Is it common to write such tests in play application, since I cannot find any decent examples or documentation of doing something like that. I used to write such tests in java web applications where integration tests load spring context, but can't find such examples in play.

Thanks in advance.

like image 700
Zygimantas Gatelis Avatar asked Aug 19 '15 20:08

Zygimantas Gatelis


1 Answers

  1. If you want to test your default configuration, starting FakeApplication, is enough. It loads modules specified in application.conf automatically. So, If it can't find UserService, that means you don't have proper module configurations in your application.conf and there for your server can't serve those requests.

    https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection

  2. If you want to use some Mockups, and override default configurations:

    https://www.playframework.com/documentation/2.4.x/ScalaTestingWithGuice

like image 171
mavarazy Avatar answered Oct 04 '22 05:10

mavarazy