Play 2.0 FakeApplication setup with test configuration

13,096

Solution 1

The problem is how to specify the test.conf file when running an intergration test using Play's FakeAppication. In my integration test I cannot call play -Dconfig.file=conf/test.conf.

What I managed to do is this:

object FakeSalatApp extends Around {

 def EmbeddedMongoTestPort: Int = 27028

 def inMemoryMongoDatabase(name: String = "default"): Map[String, String] = {
   val dbname: String = "play-test-" + scala.util.Random.nextInt
   Map(
     ("mongodb." + name + ".db" -> dbname),
     ("mongodb." + name + ".port" -> EmbeddedMongoTestPort.toString),
     ("mongodb." + name + ".replicaset.host1.host" -> "localhost"),
     ("mongodb." + name + ".replicaset.host1.port" -> EmbeddedMongoTestPort.toString),
     ("mongodb." + name + ".replicaset.host2.host" -> "localhost"),
     ("mongodb." + name + ".replicaset.host2.port" -> (EmbeddedMongoTestPort + 1).toString),
     ("mongodb." + name + ".replicaset.host3.host" -> "localhost"),
     ("mongodb." + name + ".replicaset.host3.port" -> (EmbeddedMongoTestPort + 2).toString))
  }

 override def around[T <% Result](t: => T) = {
   running(FakeApplication(additionalConfiguration = inMemoryMongoDatabase(), additionalPlugins = Seq("se.radley.plugin.salat.SalatPlugin"))) {
     t // execute t inside a http session
   }
 }
}

Solution 2

We had a similar problem loading extra configurations for our integration tests. We found populating maps manually to be tedious so we used the following approach:

private Configuration additionalConfigurations;
@Before
public void initialize(){
    Config additionalConfig = ConfigFactory.parseFile(new File("conf/integration.conf"));
    additionalConfigurations = new Configuration(additionalConfig);
}
@Test
public void testPropertiesGetLoaded() throws Exception{
    running(testServer(3333, fakeApplication(additionalConfigurations.asMap())), HTMLUNIT, new Callback<TestBrowser>(){
        public void invoke(TestBrowser browser){
            String specificProperty = Play.application().configuration().getString("specific.property");
            System.out.println(specificProperty);
        }
    });
}

I don't know if there is a nice method on the Scala side of things, we are doing all our code in java.

Solution 3

This is how I did it in Play 2.3.x

  1. Define my application GlobalSettings in a class AppGlobal in a package (not the root package)

    package configs
    
    class AppGlobal extends GlobalSettings {
      // Your application global settings
      ???
    }
    
  2. Define application global settings as object Global extends AppGlobal which is used your application.

  3. In the test class, define a test global. The test configuration is added at the end to override or add to the overall application configuration:

    object TestGlobal extends AppGlobal {
      override def onLoadConfig(config: Configuration, 
                                path: File, 
                                classloader: ClassLoader, 
                                mode: Mode): Configuration = {
        config ++ configuration ++ 
              Configuration.load(path, mode = Mode.Dev, 
                                 Map("config.file" -> "conf/test.conf"))
        }
    }
    
  4. Create the fake application with the above TestGlobal

    FakeApplication(withGlobal = Some(TestGlobal))
    

Solution 4

In my case I have simply created a base class that all my tests extend. Right before creating the FakeApplication I define the system property config.resource that sets the application's configuration. Then I have structured my configurations as follow :

application.conf : contains no-env specific configurations

test.conf : includes application.conf and defines configurations to run the unit tests

env_local.conf : includes application.conf and defines configurations to run the application locally

env_prod.conf : like env_local.conf but for production etc ...

In my project, for convenience I have crated a script local.sh that simply runs activator -Dconfig.resource=env_local.conf

@RunWith(classOf[JUnitRunner])
class ApplicationTest extends FunSuite with MockitoSugar {
   System.setProperty("config.resource", "test.conf")
   val app = Helpers.fakeApplication()
}
Share:
13,096

Related videos on Youtube

cmacher
Author by

cmacher

Updated on July 03, 2022

Comments

  • cmacher
    cmacher almost 2 years

    I have a specs2 test which uses a FakeApplication and an embedded mongodb database.

    def inMemoryMongoDatabase(name: String = "default"): Map[String, String] = {
        val dbname: String = "play-test-" + scala.util.Random.nextInt
        Map(
            ("mongodb." + name + ".db" -> dbname),
            ("mongodb." + name + ".port" -> EmbeddedMongoTestPort.toString))
    }
    
    override def around[T <% Result](t: => T) = {
        running(FakeApplication(additionalConfiguration = inMemoryMongoDatabase(), additionalPlugins = Seq("se.radley.plugin.salat.SalatPlugin"))) {
            t // execute t inside a http session
        }
    }
    

    The FakeApplication uses the default application.conf configuration in the conf directory and additional configuration for the test databases that are created for each test.
    This was working find until we setup a mongodb replicat set. Now the application.conf contains configuration for this replicat set

    mongodb.default.replicaset {
    host1.host = "localhost"
    host1.port = 27017
    host2.host = "localhost"
    host2.port = 27018
    host3.host = "localhost"
    host3.port = 27019
    }
    

    As the FakeApplication uses the default configuration the tests fail because the hosts of the replicaset cannot be found. I want to have a different configuration for my tests, basically remove the mongodb.default.replicaset entry. If mongodb.default.replicaset were a simple Map[String, String] that would be easy as I could just add it to the additonalConfiguration but when I try to do that it fails because the expected value type is not a String but an Object. I have also tried to provide a separate test.conf file to the FakeApplication via the path parameter.

    override def around[T <% Result](t: => T) = {
        running(FakeApplication(path = new java.io.File("conf/test.conf"), additionalConfiguration = inMemoryMongoDatabase(), additionalPlugins = Seq("se.radley.plugin.salat.SalatPlugin"))) {
            t // execute t inside a http session
        }
    }
    

    That didn't work either as it didn't load any config.

    I would greatly appreciate any help. Thanks.

    Chris