我对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)
...
...
}
}
}
问题是在完成测试运行后,使用mongo CLI我发现只有两个结果数据库中的一个实际存在索引。
看起来UserDAO单例对象实例在所有FakeApplications之间共享,因此对于所有测试,只有在第一次访问对象时,才会对collection.indexesManager.ensure(...)执行一次调用。
作为证明,我试图在UserDAO.insert()函数内部移动collection.indexesManager.ensure(...),实际上它解决了这个问题。
我曾经认为FakeApplications是完全孤立的应用程序实例。
答案 0 :(得分:1)
不可思议,是的,他们这样做。这使得编写并行测试非常困难(甚至不可能)。这将在Play 2.4:https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection
中发生变化