Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

app implicit is null in GuiceOneAppPerTest #107

Open
christianri opened this issue Oct 2, 2017 · 6 comments
Open

app implicit is null in GuiceOneAppPerTest #107

christianri opened this issue Oct 2, 2017 · 6 comments

Comments

@christianri
Copy link

christianri commented Oct 2, 2017

Hi Scalatest team,

I seem to have the issue that the app implicit is null when using the GuiceOneAppPerTest trait for testing. When I use GuiceOneAppPerSuite it is fine. I discovered this when investigating why my dependency injection in the test did not work as expected: Link

Scala version 2.12.3, play 2.6.3 and scalatestplus-play 3.1.2.

To reproduce:

  • Create a new play project: sbt new playframework/play-scala-seed.g8
  • Add a simple println into the test which uses GuiceOneAppPerTest: println("App object", app)

Expected result: app is defined
Actual result: app is null

If you could please investigate that is is really an issue or wrong use from my end or the g8 template. Thank you very much for this great framework!

@marcospereira
Copy link
Member

Hi @christianri, you mean something like this?

class MyTestSpec extends PlaySpec with GuiceOneAppPerTest with Injecting {
  println(s"The app = $app")

  ...
}

@christianri
Copy link
Author

Yes, like this (or as I wrote in the ticket above: println("App object", app))
I understand that you initialize app once in the actual test, where also the controller is set. But shouldn't it be set already at this stage with the first one?

@gmethvin
Copy link
Member

gmethvin commented Oct 7, 2017

Perhaps you could explain your use case a bit more?

@christianri
Copy link
Author

christianri commented Oct 9, 2017

My use case is that my play application also opens a java.net.ServerSocket.
It seems that the application is never shut down to a point where the socket is closed via the standard shutdown mechanism and as such I currently rely on a call to close the socket between tests, otherwise I get an exception that this port is already in use.

@marcospereira
Copy link
Member

@christianri thanks for the additional information.

My use case is that my play application also opens a java.net.ServerSocket.

How is the ServerSocket being opened? Do you have a Guice module to open it? If so, are you using play.api.inject.ApplicationLifecycle to register a stop hook? This would be the correct way to do it:

class MyServerSocket @Inject()(applicationLifecycle: ApplicationLifecycle) {
  val serverSocket = ??? // open the server socket somehow
  applicationLifecycle.addStopHook { () =>
    serverSocket.close()
    Future.successful(true)
  }
}

That way, Play will handle the ServerSocket life cycle together with your application.

@christianri
Copy link
Author

christianri commented Oct 10, 2017

Yes, I have it like this, the stop hook is registered. In addition, the controller that opens the socket is also started with the App via the task module ( bind[Controller].toSelf.eagerly() ).

I tested a bit further with adding a println into the stop hook code.
Once I run the test with GuiceOneAppPerSuite the stop hook is only called once, at the end of all the tests as expected.
When I run with GuiceOneAppPerTest, the stop hook is called after the test, yet the new app of the next test cannot bind to the port as it is still in use. On the surface this seems like a race condition, where the tests that execute quickly after one another don't wait for the Future of the stop hook - or the Play framework closes the app without waiting for it. Could this be the case?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants