是否可以在游戏功能测试中模拟数据库连接?如何模拟?
Is it possible to mock DB connection in play functional testing and how?
我的一些控制器依赖于数据库连接,结构如下:
def getAll(revId: Muid) = Action { implicit request =>
DB.withConnection { implicit connection =>
...
我正在尝试为它创建一个单元测试,其中包含所有模拟的依赖项,包括连接。现在,通过 Guice 可以轻松地注入依赖项。但是,我正在努力寻找一种方法来模拟隐式连接。而且,最终,测试正在尝试连接到我在测试中的默认数据库。
在这种情况下,甚至可以模拟隐式吗?如何模拟?
更新
所以,在玩了一会儿这个东西之后,我得到了以下信息:
我的 class 正在测试中:
class ChecklistCreationScheduler @Inject()(jobScheduler: JobScheduler,
dBApi: DBApi,
futureChecklistRepository: FutureChecklistRepository) extends ClassLogger{
def scheduleSingleFutureChecklistJob(futureChecklistId: Muid): Unit = {
logger.info(s"Preparing to schedule one time future checklist job for future checklist id '${futureChecklistId.uuid}'")
val db = dBApi.database("default")
logger.info("Database" + db)
db.withConnection { implicit connection =>
logger.info("Connection" + connection)
...
}
}
}
测试:
"ChecklistCreationScheduler#scheduleSingleFutureChecklistJob" should {
"schedule a single job through a scheduler" in {
val futureChecklistId = Muid.random()
val jobScheduler = mock[JobScheduler]
val connection = mock[Connection]
val DB = mock[Database]
DB.getConnection returns connection
val dbApi = mock[DBApi]
when(dbApi.database("default")).thenReturn(DB)
val futureChecklistRepository = mock[FutureChecklistRepository]
doReturn(Option.empty).when(futureChecklistRepository).getById(futureChecklistId)(connection)
val chCreationScheduler = new ChecklistCreationScheduler(jobScheduler, dbApi, futureChecklistRepository)
chCreationScheduler.scheduleSingleFutureChecklistJob(futureChecklistId) must throwA[UnexpectedException]
}
}
当我执行测试时,似乎执行甚至没有进入 withConnection
的块。 (我永远不会进入这一行:logger.info("Connection" + connection)
)。
有什么想法吗?
以下是如何使用 Dependency Injection 轻松模拟数据库调用:
考虑到这是您的控制器:
package controllers
import javax.inject.Inject
import play.api._
import play.api.db.Database
import play.api.mvc._
class Application @Inject() (database: Database) extends Controller {
def index = Action { implicit request =>
database.withConnection { implicit connection =>
???
}
Ok(views.html.index("Your new application is ready."))
}
}
你可以写一个Specification like this:
import java.sql.Connection
import controllers.Application
import org.specs2.mutable._
import org.specs2.runner._
import org.junit.runner._
import org.specs2.mock._
import play.api.db.Database
import play.api.mvc.RequestHeader
@RunWith(classOf[JUnitRunner])
class ApplicationSpec extends Specification with Mockito {
"Application" should {
"index page" in {
val connection = mock[Connection]
val database = mock[Database]
database.getConnection returns connection
val controller = new Application(database)
// You will also need to mock the request
// so that you can add the expected behavior
val request = mock[RequestHeader]
val result = controller.index(request)
// do some assert about your result
result must not beNull
}
}
}
当然,处理您的(整个)用例可能需要一些其他模拟。
我的一些控制器依赖于数据库连接,结构如下:
def getAll(revId: Muid) = Action { implicit request =>
DB.withConnection { implicit connection =>
...
我正在尝试为它创建一个单元测试,其中包含所有模拟的依赖项,包括连接。现在,通过 Guice 可以轻松地注入依赖项。但是,我正在努力寻找一种方法来模拟隐式连接。而且,最终,测试正在尝试连接到我在测试中的默认数据库。
在这种情况下,甚至可以模拟隐式吗?如何模拟?
更新
所以,在玩了一会儿这个东西之后,我得到了以下信息: 我的 class 正在测试中:
class ChecklistCreationScheduler @Inject()(jobScheduler: JobScheduler,
dBApi: DBApi,
futureChecklistRepository: FutureChecklistRepository) extends ClassLogger{
def scheduleSingleFutureChecklistJob(futureChecklistId: Muid): Unit = {
logger.info(s"Preparing to schedule one time future checklist job for future checklist id '${futureChecklistId.uuid}'")
val db = dBApi.database("default")
logger.info("Database" + db)
db.withConnection { implicit connection =>
logger.info("Connection" + connection)
...
}
}
}
测试:
"ChecklistCreationScheduler#scheduleSingleFutureChecklistJob" should {
"schedule a single job through a scheduler" in {
val futureChecklistId = Muid.random()
val jobScheduler = mock[JobScheduler]
val connection = mock[Connection]
val DB = mock[Database]
DB.getConnection returns connection
val dbApi = mock[DBApi]
when(dbApi.database("default")).thenReturn(DB)
val futureChecklistRepository = mock[FutureChecklistRepository]
doReturn(Option.empty).when(futureChecklistRepository).getById(futureChecklistId)(connection)
val chCreationScheduler = new ChecklistCreationScheduler(jobScheduler, dbApi, futureChecklistRepository)
chCreationScheduler.scheduleSingleFutureChecklistJob(futureChecklistId) must throwA[UnexpectedException]
}
}
当我执行测试时,似乎执行甚至没有进入 withConnection
的块。 (我永远不会进入这一行:logger.info("Connection" + connection)
)。
有什么想法吗?
以下是如何使用 Dependency Injection 轻松模拟数据库调用:
考虑到这是您的控制器:
package controllers
import javax.inject.Inject
import play.api._
import play.api.db.Database
import play.api.mvc._
class Application @Inject() (database: Database) extends Controller {
def index = Action { implicit request =>
database.withConnection { implicit connection =>
???
}
Ok(views.html.index("Your new application is ready."))
}
}
你可以写一个Specification like this:
import java.sql.Connection
import controllers.Application
import org.specs2.mutable._
import org.specs2.runner._
import org.junit.runner._
import org.specs2.mock._
import play.api.db.Database
import play.api.mvc.RequestHeader
@RunWith(classOf[JUnitRunner])
class ApplicationSpec extends Specification with Mockito {
"Application" should {
"index page" in {
val connection = mock[Connection]
val database = mock[Database]
database.getConnection returns connection
val controller = new Application(database)
// You will also need to mock the request
// so that you can add the expected behavior
val request = mock[RequestHeader]
val result = controller.index(request)
// do some assert about your result
result must not beNull
}
}
}
当然,处理您的(整个)用例可能需要一些其他模拟。