I've been looking at some posts on StackOverflow to see how to set up testing with a MYSQL database.
I simply want to test some controller methods which will need a test database with some data in to return meaningful results. I want to use a real MYSQL database as that is what I will be using in production and I have read that there are quite a few differences between MYSQL and the InMemory database provided by Play.
In posts such as this one and this blog about testing Play! applications, the posts show examples that initialise a FakeApplication object with database parameters and then call Helper.start(fakeApp).
The docs for Helper.start(FakeApplication app) gives the following description:
Starts a new application.
OK great. But what processes are actually triggered off by calling start and what will that give me in a test?
Map<String, String> settings = new HashMap<String, String>();
settings.put("db.default.url", "jdbc:mysql://localhost/testdb");
settings.put("db.default.user", "root");
settings.put("db.default.password", "");
app = Helpers.fakeApplication(settings);
Helpers.start(app);
I was hoping that the above code would configure Ebean to use my test database, but when I try to execute a method such as Ebean.save() I get an error saying that no default database has been registered with Ebean. In order to register I will need to populate a ServerConfig object and create an EbeanServer from the EbeanServerFactory. In that case was there any point in passing the settings map to the FakeApplication object? And again, just what does starting a FakeApplication actually do? How can it be used?
Thanks in advance.
I realize that you asked this over a year ago, but it took me quite some time to figure this out for myself, so hopefully this helps someone at some point.
With a FakeApplication running, you can do basically everything you can after saying "activator run", except that there is not a webserver (netty) running serving up requests. You can though, test your controllers, as shown here, and call methods that access the database.
I actually referenced both of those posts you mention when figuring this out, in addition to this one, which discusses some special play magic config vars that must be set you'll see in my example below.
I created an abstract FakeApplicationTest class which I extend in the Unit/Functional tests. I first use my existing application.conf file, then overwrite certain parameters to test against a different database. Once the FakeApplication is started, I read in all the evolutions and create a fresh database to run my tests against.
public abstract class FakeApplicationTest {
protected static FakeApplication app;
/**
* Create a new FakeApplication using all our custom config vars that test against diff DB's
*
* @return
*/
public static FakeApplication createFakeApp() {
// grab the main application.conf file that is used to start up the Play application
Config config = ConfigFactory.parseFile(new File("conf/application.conf"));
// resolve all variables within this config file with other variables within itself
config = ConfigFactory.load(config);
// create a Configuration object out of this and then turn it into a Map to be modified
Configuration configuration = new Configuration(config);
Map<String, Object> fakeApplicationConf = Maps.newHashMap(configuration.asMap());
// do some crazy stuff here because Play wants us to for config voodoo, see:
// http://www.stupidjavatricks.com/2013/05/changing-play-2-db-configuration-at-runtime-beware-of-dragons/
Configuration akka = configuration.getConfig("akka.actor.serialization-bindings");
addValue(fakeApplicationConf, "akka.actor.serialization-bindings", null);
addValue(fakeApplicationConf, "akka.actor.serialization-bindings.\"[B\"", akka.getString("\"[\"B"));
addValue(fakeApplicationConf, "akka.actor.serialization-bindings.\"java.io.Serializable\"", akka.getString("\"java.io.Serializable\""));
// point at a different test database
addValue(fakeApplicationConf, "db.default.url", "jdbc:mysql://127.0.0.1/testdb");
addValue(fakeApplicationConf, "db.default.user", "someuser");
addValue(fakeApplicationConf, "db.default.password", "hunter2");
// disable evolutions and just create the DB manually
addValue(fakeApplicationConf, "evolutionplugin", "disabled");
return Helpers.fakeApplication(fakeApplicationConf);
}
@BeforeClass
public static void setUp() throws Exception {
app = createFakeApp();
// fire up the Fake Application!
Helpers.start(app);
// after we start up the application, create a database
createCleanDb();
}
@AfterClass
public static void tearDown() throws Exception {
Helpers.stop(app);
}
...
}
There is quite a bit to reading out the evolutions and applying them in order too, but I've left that out for now.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With