Play-ReactiveMongo plugin: play2 testing a controller with a reactiveMongoApi - mongodb

In the following, I am using the Play2 ReactiveMongo plugin in version 0.11.0.play24 (https://github.com/ReactiveMongo/Play-ReactiveMongo)
for Play 2.4.
As mentioned in the documentation located at http://reactivemongo.org/releases/0.11/documentation/tutorial/play2.html, a Play2 controller with Mongo is instantiated as follows:
class MyController #Inject() (val reactiveMongoApi: ReactiveMongoApi)
extends Controller with MongoController with ReactiveMongoComponents { }
Therefore, since the controller is now a class and not an object, it is not possible to use it as a singleton in the test cases.
However, I do not know how to inject the reactiveMongoApi in order to instantiate a MyController() with the right parameters in a test case (ScalaCheck or other...)
Do you have any idea/example on how to test such a controller with ScalaCheck or Specs2?
Thank you in advance!

You can produce a mock for ReactiveMongoApi (depending which mock framework you use):
val reactiveMongoApi = mock[ReactiveMongoApi]
and then you can do this:
new MyController(reactiveMongoApi)
That's the simplest approach. To use the actual ReactiveMongoApi object:
val app = new GuiceApplicationBuilder()
.in(Mode.Test)
.configure("play.modules.enabled" -> "play.modules.reactivemongo.ReactiveMongoModule")
.build
val reactiveMongoApi = app.injector.instanceOf[ReactiveMongoApi]
If it gets more complicated, for example, partially mocked nested dependency tree (this is more integration testing than unit testing), you may want to partially mock the Guice framework as explained here.

This project use Guice for dependency injection, Spec2 for testing controllers, and Frisby for testing endpoints.
https://github.com/luongbalinh/play-mongo

Related

Use WSClient in scala app (play framework)

I'm not sure if there's something really basic that I'm missing, but I can't figure out how to use WSClient. I've seen all of the examples saying you need to pass the WSClient to a class as a dependency, which I've done, but when I run the program what do I actually pass to my class?
For example, my class signature is:
class myClassName(ws: WSClient)
But when I instantiate the class what do I actually pass to it? I'm also happy to ignore the Play! framework stuff if that makes it easier and just use SBT to run it (which I'm more familiar with).
It's unclear where you might be using a WSClient, but it is recommended that you let the Play framework 'manage' the instance of the client. When you instantiate your application, it gets injected:
class Application #Inject() (ws: WSClient) extends Controller {
...
}
What that means is that inside the ... you have access to ws as a value. You can instantiate myClassName using it:
class Application #Inject() (ws: WSClient) extends Controller {
val myclass = myClassName(ws) // passes the injected WSClient to myClassName
}
Or you can write a function that returns the WSClient, so some other area of your code can call into your Application object to get a object handler for it.
But the key is that the Application object gets that handle because of injection, which is the #Inject annotation.
If you need to generate a WSClient and manage it manually, there are good instructions here. The recommended implementation is reliant on Play! framework libraries, but doesn't depend on the Application.

Alternative to using Akka.system inside an object

I am learning the Play Framework together with Scala, and I looked at the reactive-stocks tutorial that comes with activator for learning more about the framework.
In the learning project that I am creating (a simple chat) I want to have something similar to this snippet taken out from the tutorial:
object StocksActor {
lazy val stocksActor: ActorRef = Akka.system.actorOf(Props(classOf[StocksActor]))
}
That is, an actor that will only be instanciated one time on the application. But I found out that Akka.system is deprecated, so I should use dependency injection to get the ActorSystem. How would I do dependency injection in an Object?
object ChatRoomsActor #Inject() (actorSystem: ActorSystem) {
lazy val ref: ActorRef = actorSystem.actorOf(Props(classOf[ChatRoomsActor]))
}
I tried this code, but it doesn't work.

Scala and Slick: DatabaseConfigProvider in standalone application

I have an Play 2.5.3 application which uses Slick for reading an object from DB.
The service classes are built in the following way:
class SomeModelRepo #Inject()(protected val dbConfigProvider: DatabaseConfigProvider) {
val dbConfig = dbConfigProvider.get[JdbcProfile]
import dbConfig.driver.api._
val db = dbConfig.db
...
Now I need some standalone Scala scripts to perform some operations in the background. I need to connect to the DB within them and I would like to reuse my existing service classes to read objects from DB.
To instantiate a SomeModelRepo class' object I need to pass some DatabaseConfigProvider as a parameter. I tried to run:
object SomeParser extends App {
object testDbProvider extends DatabaseConfigProvider {
def get[P <: BasicProfile]: DatabaseConfig[P] = {
DatabaseConfigProvider.get("default")(Play.current)
}
}
...
val someRepo = new SomeModelRepo(testDbProvider)
however I have an error: "There is no started application" in the line with "(Play.current)". Moreover the method current in object Play is deprecated and should be replaced with DI.
Is there any way to initialize my SomeModelRepo class' object within the standalone object SomeParser?
Best regards
When you start your Play application, the PlaySlick module handles the Slick configurations for you. With it you have two choices:
inject DatabaseConfigProvider and get the driver from there, or
do a global lookup via DatabaseConfigProvider.get[JdbcProfile](Play.current), which is not preferred.
Either way, you must have your Play app running! Since this is not the case with your standalone scripts you get the error: "There is no started application".
So, you will have to use Slick's default approach, by instantiating db directly from config:
val db = Database.forConfig("default")
You have lot's of examples at Lightbend's templates.
EDIT: Sorry, I didn't read the whole question. Do you really need to have it as another application? You can run your background operations when your app starts, like here. In this example, InitialData class is instantiated as eager singleton, so it's insert() method is run immediately when app starts.

Play 2.5 + Slick + DI Issue

I have DAO defined as follows:
#Singleton
class MyDAO #Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
I have an integration test which references this DAO:
class SomeIntegrationTest {
lazy val someVal = new MyDAO
}
How can I inject the DatabaseConfigProvider into the MyDAO in the SomeIntegrationTest? I cannot inject one in the constructor of the test because test classes do not take constructor parameters.
You can get your dependency injected by doing
val dbConfigProvider = app.injector.instanceOf[DatabaseConfigProvider]
where app is an instance of your FakeApplication. Without it, there is no way Play can inject your dependency for you. You can get an instance of FakeApplication by extending OneAppPerSuite, see the provided link for more details.
In general, there are three main ways you can gain access to some object(s) in your test:
manual creation of objects using the new keyword (not considered best practice)
injection via injector as shown here (either injecting objects directly or injecting a provider/factory which can get them for you)
in case of unit testing a class with some dependencies, having those dependencies mocked

Scala Play 2.4: How to pass MessagesApi explicitly?

I created a small CRUD application to learn more about Scala and Play. Following the CRUD template, I obtained the solution posted here on GitHub.
I have been struggling to develop effective tests for this using Specs2. Now I would like to test the controller. It has this signature:
class PersonController #Inject() (repo: PersonRepository, val messagesApi: MessagesApi)
(implicit ec: ExecutionContext) extends Controller with I18nSupport
To test an action of the controller, I should create a new controller. While I see how I can mock away the repository and the WithApplication trait will provide the ExecutionContext, I don't see how to deal with the MessagesApi.
1) Shall I create an instance of it or retrieve it from somewhere and pass explicitly? how?
2) Shall I mock it too? how?
Thank you for your help.
For unit tests, I would go with a mock. Both specs2 (docs) and ScalaTest (docs) have some level of integration with Mockito.
For functional tests, I would go with using WithApplication scope (in the case of specs2) and using the app injector to create the controller instance:
"should test using an injected controller" in new WithApplication {
val applicationController = app.injector.instanceOf[controllers.Application]
val result: Future[mvc.Result] = applicationController.index()(FakeRequest())
status(result) must equalTo(OK)
}
This way, Play injector will create your controller instance with all the necessary dependencies, including MessageApi.