Я новичок в Play2 и Scala. Я пишу простое приложение, использующее плагин ReactiveMongo.
Я написал простой объект для использования в качестве 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")))
}
}
Все идет нормально. Проблемы приходят с тестами спецификаций. У меня есть два набора тестов, и я настроил их для работы с разными базами данных. Первый набор тестов использует базу данных «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 mongo я вижу, что только в одной из двух полученных баз данных индекс действительно присутствует.
Похоже, экземпляр одноэлементного объекта UserDAO является общим для всех FakeApplications, поэтому вызов collection.indexesManager.ensure(...) выполняется только один раз для всех тестов, когда к объекту обращаются в первый раз.
В качестве доказательства я попытался переместить вызов collection.indexesManager.ensure(...) внутрь функции UserDAO.insert(), и на самом деле это решает проблему.
Раньше я думал о FakeApplications как о полностью изолированных экземплярах приложения.