2012-09-03 22 views
9

Mam test specs2, który wykorzystuje FakeApplication i osadzoną bazę danych mongodb.Play 2.0 Konfiguracja FakeApplication z konfiguracją testową

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

FakeApplication korzysta z domyślnej konfiguracji application.conf w katalogu conf i dodatkowej konfiguracji dla baz danych testowych, które są tworzone dla każdego testu.
To działało, dopóki nie skonfigurujemy zestawu replik mongodów. Teraz application.conf zawiera konfigurację dla tego replicat ustawić

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

Jak FakeApplication wykorzystuje domyślną konfigurację testów zakończy się niepowodzeniem, ponieważ nie można znaleźć gospodarzami replicaset. Chcę mieć inną konfigurację dla moich testów, zasadniczo usuń wpis mongodb.default.replicaset. Jeśli mongodb.default.replicaset był prosty Map [String, String], który byłby łatwy, ponieważ mógłbym dodać go do additonalConfiguration, ale gdy próbuję to zrobić, to się nie uda, ponieważ oczekiwany typ wartości nie jest ciągiem, ale obiektem. Próbowałem również dostarczyć oddzielny plik test.conf do FakeApplication za pośrednictwem parametru ścieżki.

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

To nie działało, ponieważ nie załadowało żadnej konfiguracji.

Byłbym wdzięczny za każdą pomoc. Dzięki.

Chris

Odpowiedz

3

Problem polega na określeniu pliku test.conf podczas uruchamiania testu integracji z użyciem FakeAppication Play. W moim teście integracji nie mogę zadzwonić pod numer play -Dconfig.file=conf/test.conf.

Co udało mi się zrobić to w ten sposób:

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

Korzystanie path nie będzie działać tutaj, ponieważ jest to ścieżka FakeApplication którego używasz (może mieć inną ścieżkę w niektórych przypadkach).

W twoim przypadku sugeruję określenie test.conf podczas uruchamiania gry w trybie testowym, np.

play -Dconfig.file=conf/test.conf 

Zostanie odebrany test.conf. Możesz wtedy również dodać normalne application.conf i zastąpić tylko ustawienia mongo.

Być może miałoby również sens, aby "tryb pojedynczego celu" był domyślnym sposobem łączenia się z mongotb w twoim application.conf i zastąpienie konfiguracji mongobowej, aby użyć repliki tylko w konfiguracji produkcyjnej.

10

Mieliśmy podobny problem z ładowaniem dodatkowe konfiguracje do testów integracyjnych. Znaleźliśmy wypełniania mapy ręcznie być nudny więc stosować następujące podejście:

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

ja nie wiem, czy tam jest miłym sposobem na boku Scala rzeczy, robimy wszystkie nasze kodu w Javie.

2

Tak właśnie zrobiłem w wersji 2.3.x

  1. Definiowanie mojej aplikacji GlobalSettings w klasie AppGlobal w opakowaniu (nie pakiet korzeń)

    package configs 
    
    class AppGlobal extends GlobalSettings { 
        // Your application global settings 
        ??? 
    } 
    
  2. Definiowanie globalnych ustawień aplikacji jak object Global extends AppGlobal który służy swoją aplikację.

  3. W klasie testowej zdefiniuj test globalny. Konfiguracja testu dodaje na koniec, aby zastąpić lub dodać do ogólnej konfiguracji aplikacji:

    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. stworzyć fałszywą aplikację z powyższym TestGlobal

    FakeApplication(withGlobal = Some(TestGlobal)) 
    
1

w moim przypadku mam po prostu stworzyłem klasę bazową, którą rozszerzają wszystkie moje testy. Tuż przed utworzeniem FakeApplication definiuję właściwość systemową config.resource, która ustawia konfigurację aplikacji. Potem moje konfiguracje zostały skonstruowane w sposób następujący:

application.conf: zawiera nie-env specyficzne konfiguracje

test.conf: obejmuje application.conf i określa konfiguracje, aby uruchomić urządzenie testuje

env_local. conf: obejmuje application.conf i określa konfiguracje, aby uruchomić aplikację lokalnie

env_prod.conf: jak env_local.conf ale do produkcji etc ...

W moim projekcie dla wygody napisałem skrypt local.sh , który po prostu uruchamia aktywator -Dconfig.resource = env_local.conf

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