2015-04-24 2 views
3

Я совершенно новый для Play2 и Scala. Я пишу простое приложение, которое использует плагин ReactiveMongo.Play2 Framework/Scala/Specs2 - Разделяют ли другие объекты FakeApplications объекты Singleton?

Я написал простой объект для использования в качестве DAO

object UserDAO { 
    def db: reactivemongo.api.DB = ReactiveMongoPlugin.db 
    def collection: JSONCollection = db.collection[JSONCollection]("users") 

    collection.indexesManager.ensure(Index(List("name" -> IndexType.Ascending), 
    unique = true)) 

    def insert(User): Future[LastError] = { 
    collection.insert(unit) 
    } 

    def findOne(query: JsObject): Future[Option[User]] = { 
    collection.find(query).one[User] 
    } 

    def removeOne(query: JsObject): Future[LastError] = { 
    collection.remove(query, firstMatchOnly = true) 
    } 

    ... 
} 

Обратите внимание, что я создать индекс для того, чтобы два пользователя с таким же именем не может быть создан. Таким образом, я могу использовать DAO в своих контроллерах, как следовать

class Users extends Controller with MongoController { 
    def createUser = Action.async(parse.json) { 
    request => 
     request.body.validate[User].map { 
     user => 
      UserDAO.insert(user).map { 
      lastError => 
       Created(s"User Created") 
      } 
     }.getOrElse(Future.successful(BadRequest("invalid json"))) 
    } 
} 

До сих пор так хорошо. Проблемы приходят с Specs Tests. У меня есть два набора тестов, и я настроил их для работы с различными базами данных. Первый набор тестов использует базу данных «mydb1»:

val addConf = Map("mongodb.uri" -> ("mongodb://localhost:27017/mydb1")) 

class UsersTest1 extends PlaySpecification { 
    sequential 

    "Users" should { 
    "create a User" in new WithApplication(FakeApplication(
          additionalConfiguration = addConf)) { 
     val request = FakeRequest(POST, "/user") 
     .withJsonBody(Json.obj(
      "name" -> "foo", 
      "age" -> 3)) 

     val response = route(request) 
     ... 
     ... 
    } 
    } 
} 

Второй набор тестов использует базу данных «mydb2»

val addConf = Map("mongodb.uri" -> ("mongodb://localhost:27017/mydb2")) 

class UsersTest2 extends PlaySpecification { 
    sequential 

    "Users" should { 
    "create a User" in new WithApplication(FakeApplication(
          additionalConfiguration = addConf)) { 
     val request = FakeRequest(POST, "/user") 
     .withJsonBody(Json.obj(
      "name" -> "foo", 
      "age" -> 3)) 

     val response = route(request) 
     ... 
     ... 
    } 
    } 
} 

Проблема заключается в том, что после полного выполнения теста, с помощью CLI Монго Я вижу, что только в одной из двух результирующих баз данных фактически присутствует индекс.

Похоже, что экземпляр объекта Singleton UserDAO разделяется между всеми FakeApplications, так что вызов функции collection.indexesManager.ensure (...) выполняется только один раз для всех тестов, когда объект обращается к первому время.

В качестве доказательства этого я попытался переместить вызов collection.indexesManager.ensure (...) внутри функции UserDAO.insert(), и на самом деле он решает проблему.

Раньше я думал, что FakeApplications является полностью изолированным экземпляром приложения.

ответ

1

Непознанное, да, они делают. Это делает запись параллельных тестов очень сложной (или даже невозможной). Это изменится в Play 2.4: https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection

+0

Или вы можете управлять соединениями ReactiveMongo самостоятельно. Поскольку RM предоставляет пулы, это не повлияет на производительность. – cchantep