2012-09-03 11 views
9

Tengo una prueba specs2 que utiliza una aplicación Fake y una base de datos mongodb integrada.Play 2.0 FakeApplication setup with test configuration

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 
    } 
} 

El FakeApplication utiliza la configuración por defecto application.conf en el directorio conf y configuración adicional para las bases de datos de prueba que se crean para cada prueba.
Esto funcionó hasta que configuramos un conjunto de réplica mongodb. Ahora el application.conf contiene configuración para este RepliCat establece

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

Como el FakeApplication utiliza la configuración por defecto las pruebas fallan debido a que los anfitriones de la replicaSet no se pueden encontrar. Quiero tener una configuración diferente para mis pruebas, básicamente eliminar la entrada mongodb.default.replicaset. Si mongodb.default.replicaset fuera un simple Map [String, String], sería fácil, ya que podría agregarlo a la configuración adicional, pero cuando intento hacerlo, falla porque el tipo de valor esperado no es una cadena, sino un objeto. También he intentado proporcionar un archivo test.conf por separado a FakeApplication a través del parámetro path.

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 
    } 
} 

Eso tampoco funcionó ya que no cargó ninguna configuración.

Agradeceria cualquier ayuda. Gracias.

Chris

Respuesta

3

El problema es cómo especificar el archivo test.conf cuando se ejecuta una prueba de integración utilizando la aplicación Fake de Play. En mi prueba de integración no puedo llamar al play -Dconfig.file=conf/test.conf.

lo que he conseguido hacer es esto:

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 
    } 
} 
} 
0

Usando path no funcionará aquí, ya que este es el camino de la FakeApplication se está ejecutando (es posible que tenga un camino diferente en algunos casos).

Lo que sugeriría en su caso es especificar un test.conf al ejecutar Play para modo de prueba, como p. Ej.

play -Dconfig.file=conf/test.conf 

Luego test.conf serán recogidos. También podría hacer que incluya su normal application.conf y anular solo la configuración de mongo.

Quizás también tendría sentido tener el "modo de destino único" como la manera predeterminada de conectarse a mongodb en su application.conf, y sobrescribir la configuración de mongob para usar un conjunto de réplicas solo en una configuración de producción.

10

Hemos tenido un problema similar cargar configuraciones adicionales para nuestras pruebas de integración. Encontramos que pueblan mapas manualmente a ser tedioso así que utilizamos el siguiente enfoque:

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); 
     } 
    }); 
} 

No sé si hay un buen método en el lado Scala de las cosas, estamos haciendo todo nuestro código en Java.

2

Así lo hice en Play 2.3.x

  1. Definir mi solicitud GlobalSettings en una clase AppGlobal en un paquete (no el paquete raíz)

    package configs 
    
    class AppGlobal extends GlobalSettings { 
        // Your application global settings 
        ??? 
    } 
    
  2. Definir la configuración global de aplicaciones como object Global extends AppGlobal que se utiliza la aplicación.

  3. En la clase de prueba, defina una prueba global. Se añade la configuración de prueba en el extremo de anular o añadir a la configuración de la aplicación general:

    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. crear la aplicación falsa con lo anterior TestGlobal

    FakeApplication(withGlobal = Some(TestGlobal)) 
    
1

En mi caso tengo simplemente Creé una clase base que extienden todas mis pruebas. Justo antes de crear FakeApplication, defino la propiedad del sistema config.resource que establece la configuración de la aplicación. entonces he estructurado mis configuraciones de la siguiente manera:

application.conf: no contiene env configuraciones específicas

test.conf: incluye application.conf y define configuraciones para ejecutar la unidad de prueba

env_local. conf: incluye application.conf y define configuraciones para ejecutar la aplicación localmente

env_prod.conf: como env_local.conf pero para la producción etc ...

En mi proyecto, para mayor comodidad he creado un script local.sh que simplemente ejecuta el activador -Dconfig.resource = env_local.conf

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