Testing Play + Slick

I have a simple CRUD application built with Scala Play 2.4.3 and Play-slick 1.1.0 ( slick 3.1.0 ), which uses a MySQL database for permanent storage.

I tried to create tests for my application, and I saw 2 main options:

  • mocking access to the database, which, as far as I saw, requires some code changes.
  • make tests use an alternative database (possibly in H2 memory).

What is the best approach (advantages and disadvantages)?

I prefer the second approach, but I find some difficulties in setting up the tests.

What do I need to do? First, I think I need to run tests with FakeApplication , right? Do I need any sbt dependency to be able to do this?

After that, how can I tell you to use the H2 database?

+5
source share
2 answers

My solution was to add step(Play.start(fakeApp)) at the beginning of each specification and step(Play.stop(fakeApp)) at the end of each specification.

also:

 def fakeApp: FakeApplication = { FakeApplication(additionalConfiguration = Map( "slick.dbs.default.driver" -> "slick.driver.H2Driver$", "slick.dbs.default.db.driver" -> "org.h2.Driver", "slick.dbs.default.db.url" -> "jdbc:h2:mem:play" )) 

}

This was necessary because I use play-slick , which requires configurations such as:

 slick.dbs.default.driver = "slick.driver.MySQLDriver$" slick.dbs.default.db.driver = "com.mysql.jdbc.Driver" slick.dbs.default.db.url = "jdbc:mysql://localhost/database" slick.dbs.default.db.user = "user" slick.dbs.default.db.password = "password" 

additional information about docs

+3
source

I had the same struggle and came up with such a solution (using the second approach):

Create a context for using DAO:

 trait BaseContext{ def dbName: String val dbConfig = DatabaseConfigProvider.get[JdbcProfile](dbName) val db = dbConfig.db val profile = dbConfig.driver val tables = new Tables { // this is generated by Schema Code Generator override val profile: JdbcProfile = dbConfig.driver } } @Singleton class AppContext extends BaseContext{ def dbName = "mysql" // name in your conf right after "slick.dbs" } @Singleton class TestingContext extends BaseContext{ def dbName = "h2" } 

Then create a module to bind the injection and don't forget to include it in conf using play.modules.enabled += "your.Module" :

 class ContextModule(environment: Environment, configuration: Configuration) extends AbstractModule { override def configure(): Unit = { if (configuration.getString("app.mode").contains("test")) { bind(classOf[BaseContext]) .to(classOf[TestingContext]) } else { bind(classOf[BaseContext]) .to(classOf[AppContext]) } } } 

And add it to every DAO you create:

 class SomeDAO @Inject()(context: BaseContext){ val dbConfig = context.dbConfig val db = context.db val tables = context.tables import tables.profile.api._ def otherStuff.... // you can call db.run(...), tables.WhateverYourTableIs, tables.TableRowCaseClass, ... } 

And the last step, your configuration file. In my case, I used app.mode to indicate the environment, and I use a separate .conf for another environment. The reason is that in this conf you must have the correct database configuration. Here's a sample:

 app.mode = "test" # Database configuration slick.dbs = { # for unit test h2 { driver = "slick.driver.H2Driver$" db = { url = "jdbc:h2:mem:test;MODE=MYSQL" driver = "org.h2.Driver" keepAliveConnection = true } } } 

I am sure that my solution is not elegant, but it delivers the goods. :) Any best solution is welcome!

+5
source

Source: https://habr.com/ru/post/1237070/


All Articles