pmichna
pmichna

Reputation: 4888

How to declare second database for testing in Play Framework?

I want to run unit tests on a database other than the default one. Here is my application.conf:

application.secret="[cut]"
application.langs="en"

db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost:3306/city_game?characterEncoding=UTF-8"
db.default.user=root
db.default.password=""

db.test.driver=com.mysql.jdbc.Driver
db.test.url="jdbc:mysql://localhost:3306/play_test?characterEncoding=UTF-8"
db.test.user=root
db.test.password=""

ebean.default="models.*"
ebean.test="models.*"

logger.root=ERROR
logger.play=INFO
logger.application=DEBUG

BaseModelTest.java:

package models;

import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.server.ddl.DdlGenerator;
import com.avaje.ebean.config.dbplatform.MySqlPlatform;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import play.test.FakeApplication;
import play.test.Helpers;

import java.io.IOException;

public class BaseModelTest
{
    public static FakeApplication app;
    public static DdlGenerator ddl;

    @BeforeClass
    public static void startApp() throws IOException
    {
        app = Helpers.fakeApplication();
        Helpers.start(app);

        String serverName = "test";
        EbeanServer server = Ebean.getServer(serverName);
        ServerConfig config = new ServerConfig();
        ddl = new DdlGenerator();
        ddl.setup((SpiEbeanServer) server, new MySqlPlatform(), config);
    }

    @AfterClass
    public static void stopApp()
    {
        Helpers.stop(app);
    }

    @Before
    public void dropCreateDb() throws IOException
    {

        // Drop
        ddl.runScript(false, ddl.generateDropDdl());
        // Create
        ddl.runScript(false, ddl.generateCreateDdl());
    }
}

However, I get results saved in the default database, and the test one has its tables created but empty. What I expect is to have the results written to the test db and default one untouched.

Upvotes: 2

Views: 1979

Answers (2)

leonardinius
leonardinius

Reputation: 142

I somehow ended with different approach. I still created separate real test database instance (because of stored procedures), but instead I used the Play1-like approach.

I have separates configuration sides beneath my main configuration (e.g. test configuration, prod specific stuff, stage specific stuff etc ..)

I load it via Global.scala as shown below (please note the exaple provided below works in in Play for java developers version as well)

object Global extends GlobalSettings {
  override def onLoadConfig(config: Configuration, path: File, cl: ClassLoader, mode: Mode.Mode): Configuration = {
     val modeFile: String = s"application.${mode.toString.toLowerCase}.conf"

     Logger.error(s"Loading {${path.toURI}conf/application.conf}")
     Logger.error(s"Appending mode specific configuration {${path.toURI}conf/$modeFile}")
     val modeConfig = config ++ Configuration(ConfigFactory.load(modeFile))

     super.onLoadConfig(modeConfig, path, cl, mode)
   }
}

And the application.test.conf config file is as follows:

# test database
db.default.logStatements=false
db.default.jndiName=DefaultDS
db.default.url="jdbc:postgresql://127.0.0.1:5432/db-test"
db.default.user=user
db.default.password="password!@#$"
db.default.driver=org.postgresql.Driver

This way I get following benefits:

  • I still write my tests the usual way
  • Play evolutions gets tested on CI / jenkins as well
  • I have to write my tests in the way I could safely retun them on the existing db instance w/ minimal assumptions about data and userbase. That way I'm 90% certain I will be able to run those against staging / prod environment with much less friction. (Controversial point)

Upvotes: 1

Ahmed Aswani
Ahmed Aswani

Reputation: 8649

I think you should separate your code

as these

 @BeforeClass
    public static void startApp() throws IOException {

        app = Helpers.fakeApplication();
        Helpers.start(app);
    }

 @Before
    public void dropCreateDb() throws IOException {

        String serverName = "test";

        EbeanServer server = Ebean.getServer(serverName);

        ServerConfig config = new ServerConfig();

        DdlGenerator ddl = new DdlGenerator((SpiEbeanServer) server, new MySqlPlatform(), config);

        // Drop
        ddl.runScript(false, ddl.generateDropDdl());

        // Create
        ddl.runScript(false, ddl.generateCreateDdl());
    }

Upvotes: 0

Related Questions