问题
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
回答1:
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.
回答2:
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
}
}
}
回答3:
This is how I did it in Play 2.3.x
Define my application
GlobalSettings
in a classAppGlobal
in a package (not the root package)package configs class AppGlobal extends GlobalSettings { // Your application global settings ??? }
Define application global settings as
object Global extends AppGlobal
which is used your application.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")) } }
Create the fake application with the above
TestGlobal
FakeApplication(withGlobal = Some(TestGlobal))
回答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()
}
回答5:
Using path
won't work here, since this is the path of the FakeApplication you're running (you might have a different path in some cases).
What I'd suggest in your case is to specify a test.conf
when running Play for test mode, like e.g.
play -Dconfig.file=conf/test.conf
Then test.conf
will be picked up. You could then also have it include your normal application.conf
and override just the mongo settings.
Perhaps it would also make sense to have the "single target mode" the default way of connecting to mongodb in your application.conf
, and overwrite the mongob configuration to use a replicaset only in a production configuration.
来源:https://stackoverflow.com/questions/12246686/play-2-0-fakeapplication-setup-with-test-configuration