带有 reactivemongo 进程的 embedmongo 不退出
embedmongo with reactivemongo process does not exit
我正在尝试使用 ScalaTest + embedmongo + reactivemongo 进行一些测试,但我失败了。我的第一个问题是,在测试 mongod 进程后没有关闭,我在控制台中收到此消息:
INFO: stopOrDestroyProcess: process has not exited
并且测试暂停,直到我手动终止进程。即使我的测试主体为空,也会发生这种情况。我是运行windows8.1.
另一个问题是,当我尝试使用 reactive mongo 连接到 db inside test 并向 db 插入任何内容时,我得到了这个异常:
reactivemongo.core.errors.ConnectionNotInitialized: MongoError['Connection is missing metadata (like protocol version, etc.) The connection pool is probably being initialized.']
我完全不知道如何设置它。这是我的测试代码:
package model
import com.github.simplyscala.MongoEmbedDatabase
import org.scalatest.{OptionValues, Matchers, BeforeAndAfter, FlatSpec}
import reactivemongo.api.MongoDriver
import reactivemongo.api.collections.bson.BSONCollection
import scala.concurrent.duration._
import reactivemongo.bson.BSONDocument
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
class MongoBookingRepositoryTest extends FlatSpec
with Matchers
with OptionValues
with MongoEmbedDatabase
with BeforeAndAfter {
"A MongoBookingRepository" should "..." in withEmbedMongoFixture(port = 12345) { mongoProps =>
val driver = new MongoDriver
val connection = driver.connection("localhost:12345" :: Nil)
val db = connection("testDatabase")
val collection = db.collection[BSONCollection]("bookings")
val future = collection.insert(BSONDocument("a" -> 5))
println(Await.result(future, 3.seconds))
driver.close()
connection.close()
}
}
在 play2.4 中,我尝试了下面的方法,它成功了。
依赖项:
"org.reactivemongo" %% "play2-reactivemongo" % "0.11.7.play24",
"org.reactivemongo" %% "reactivemongo-extensions-json" % "0.11.7.play24",
// test
"org.scalatest" %% "scalatest" % "2.2.4" % Test,
"de.flapdoodle.embed" % "de.flapdoodle.embed.mongo" % "1.50.0" % Test,
"org.mockito" % "mockito-core" % "1.10.19" % Test
TestMongoSetup:
import de.flapdoodle.embed.mongo.config.{Net, MongodConfigBuilder}
import de.flapdoodle.embed.mongo.distribution.Version
import de.flapdoodle.embed.mongo.{MongodStarter, MongodProcess, MongodExecutable}
import de.flapdoodle.embed.process.runtime.Network
import org.mockito.Mockito._
import play.modules.reactivemongo.ReactiveMongoApi
import reactivemongo.api.MongoConnection.ParsedURI
import reactivemongo.api.{MongoConnectionOptions, MongoDriver, MongoConnection}
import scala.concurrent.ExecutionContext
trait TestMongoSetup {
private var port : Int = _
private var mongodExe: MongodExecutable = _
private var mongodProcess: MongodProcess = _
def start(intiAtPort: Int): Unit = {
port=intiAtPort
mongodExe = MongodStarter.getDefaultInstance.prepare(
new MongodConfigBuilder()
.version(Version.Main.V3_0)
.net(new Net(port, Network.localhostIsIPv6()))
.build()
)
mongodProcess = mongodExe.start()
}
def stop(): Unit = {
mongodProcess.stop()
mongodExe.stop()
}
def createConnection(): MongoConnection = {
val driver = new MongoDriver
driver.connection(ParsedURI(
hosts = List(("localhost", port)),
options = MongoConnectionOptions(),
ignoredOptions = List.empty[String],
db = None,
authenticate = None
))
}
def createMockedReactiveMongoApi(dbName: String)(implicit ctx: ExecutionContext): ReactiveMongoApi = {
val connection = createConnection()
val db = connection(dbName)
val api = mock(classOf[ReactiveMongoApi])
doReturn(db).when(api).db
doReturn(connection).when(api).connection
api
}
}
测试类:
import db.TestMongoSetup
import models.dao.UserDAO
import org.scalatest._
import play.modules.reactivemongo.ReactiveMongoApi
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
class UserServiceTest extends FlatSpec with ShouldMatchers with GivenWhenThen with BeforeAndAfterAll with TestMongoSetup { private var mockedAPI: ReactiveMongoApi = _
var dao: UserDAO = _
val port : Int = 12345
override def beforeAll(): Unit = {
start(port)
mockedAPI = createMockedReactiveMongoApi("testDB")
dao = new UserDAO(mockedAPI)
}
override def afterAll(): Unit = {
mockedAPI.connection.actorSystem.shutdown()
mockedAPI.connection.actorSystem.awaitTermination()
stop()
}
"Check" should "check User object into DB" in {
Given("a user info")
val email = "xyx@abc.com"
val pwd= "abcddd"
When("it fetch from DB")
val fromDBUser = Await.result(dao.fetch(email,pwd), Duration.Inf)
Then("it should be fetched")
fromDBUser.get.email should equal(email)
}
}
withEmbedMongo夹具效果不佳。
更喜欢使用 "classic" 方式:https://github.com/SimplyScala/scalatest-embedmongo#basic-usage-mutable-way
对于 Mongo 3 使用 2.3_SNAPSHOT 版本的库。
我正在尝试使用 ScalaTest + embedmongo + reactivemongo 进行一些测试,但我失败了。我的第一个问题是,在测试 mongod 进程后没有关闭,我在控制台中收到此消息:
INFO: stopOrDestroyProcess: process has not exited
并且测试暂停,直到我手动终止进程。即使我的测试主体为空,也会发生这种情况。我是运行windows8.1.
另一个问题是,当我尝试使用 reactive mongo 连接到 db inside test 并向 db 插入任何内容时,我得到了这个异常:
reactivemongo.core.errors.ConnectionNotInitialized: MongoError['Connection is missing metadata (like protocol version, etc.) The connection pool is probably being initialized.']
我完全不知道如何设置它。这是我的测试代码:
package model
import com.github.simplyscala.MongoEmbedDatabase
import org.scalatest.{OptionValues, Matchers, BeforeAndAfter, FlatSpec}
import reactivemongo.api.MongoDriver
import reactivemongo.api.collections.bson.BSONCollection
import scala.concurrent.duration._
import reactivemongo.bson.BSONDocument
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Await
class MongoBookingRepositoryTest extends FlatSpec
with Matchers
with OptionValues
with MongoEmbedDatabase
with BeforeAndAfter {
"A MongoBookingRepository" should "..." in withEmbedMongoFixture(port = 12345) { mongoProps =>
val driver = new MongoDriver
val connection = driver.connection("localhost:12345" :: Nil)
val db = connection("testDatabase")
val collection = db.collection[BSONCollection]("bookings")
val future = collection.insert(BSONDocument("a" -> 5))
println(Await.result(future, 3.seconds))
driver.close()
connection.close()
}
}
在 play2.4 中,我尝试了下面的方法,它成功了。
依赖项:
"org.reactivemongo" %% "play2-reactivemongo" % "0.11.7.play24",
"org.reactivemongo" %% "reactivemongo-extensions-json" % "0.11.7.play24",
// test
"org.scalatest" %% "scalatest" % "2.2.4" % Test,
"de.flapdoodle.embed" % "de.flapdoodle.embed.mongo" % "1.50.0" % Test,
"org.mockito" % "mockito-core" % "1.10.19" % Test
TestMongoSetup:
import de.flapdoodle.embed.mongo.config.{Net, MongodConfigBuilder}
import de.flapdoodle.embed.mongo.distribution.Version
import de.flapdoodle.embed.mongo.{MongodStarter, MongodProcess, MongodExecutable}
import de.flapdoodle.embed.process.runtime.Network
import org.mockito.Mockito._
import play.modules.reactivemongo.ReactiveMongoApi
import reactivemongo.api.MongoConnection.ParsedURI
import reactivemongo.api.{MongoConnectionOptions, MongoDriver, MongoConnection}
import scala.concurrent.ExecutionContext
trait TestMongoSetup {
private var port : Int = _
private var mongodExe: MongodExecutable = _
private var mongodProcess: MongodProcess = _
def start(intiAtPort: Int): Unit = {
port=intiAtPort
mongodExe = MongodStarter.getDefaultInstance.prepare(
new MongodConfigBuilder()
.version(Version.Main.V3_0)
.net(new Net(port, Network.localhostIsIPv6()))
.build()
)
mongodProcess = mongodExe.start()
}
def stop(): Unit = {
mongodProcess.stop()
mongodExe.stop()
}
def createConnection(): MongoConnection = {
val driver = new MongoDriver
driver.connection(ParsedURI(
hosts = List(("localhost", port)),
options = MongoConnectionOptions(),
ignoredOptions = List.empty[String],
db = None,
authenticate = None
))
}
def createMockedReactiveMongoApi(dbName: String)(implicit ctx: ExecutionContext): ReactiveMongoApi = {
val connection = createConnection()
val db = connection(dbName)
val api = mock(classOf[ReactiveMongoApi])
doReturn(db).when(api).db
doReturn(connection).when(api).connection
api
}
}
测试类:
import db.TestMongoSetup
import models.dao.UserDAO
import org.scalatest._
import play.modules.reactivemongo.ReactiveMongoApi
import scala.concurrent.Await
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
class UserServiceTest extends FlatSpec with ShouldMatchers with GivenWhenThen with BeforeAndAfterAll with TestMongoSetup { private var mockedAPI: ReactiveMongoApi = _
var dao: UserDAO = _
val port : Int = 12345
override def beforeAll(): Unit = {
start(port)
mockedAPI = createMockedReactiveMongoApi("testDB")
dao = new UserDAO(mockedAPI)
}
override def afterAll(): Unit = {
mockedAPI.connection.actorSystem.shutdown()
mockedAPI.connection.actorSystem.awaitTermination()
stop()
}
"Check" should "check User object into DB" in {
Given("a user info")
val email = "xyx@abc.com"
val pwd= "abcddd"
When("it fetch from DB")
val fromDBUser = Await.result(dao.fetch(email,pwd), Duration.Inf)
Then("it should be fetched")
fromDBUser.get.email should equal(email)
}
}
withEmbedMongo夹具效果不佳。
更喜欢使用 "classic" 方式:https://github.com/SimplyScala/scalatest-embedmongo#basic-usage-mutable-way
对于 Mongo 3 使用 2.3_SNAPSHOT 版本的库。