Play/Scala 将对象注入控制器进行测试
Play/Scala injecting Object into controller for testing
我看到了这个帖子我有类似的问题,但我的问题是如何注入对象来测试控制器。
控制器
@Singleton
class ExampleCtrl @Inject() (dao: TestDAO) extends Controller {
//code here
def testMethod = Action { request =>
dao.exampleMethod()
Ok(Json.obj("test" -> "test")
}
}
DAO
class TestDAO @Inject()(protected val provider: DatabaseConfigProvider){
def exampleMethod()
}
测试
class ExampleCtrlSpec extends PlaySpec with MockitoSugar {
val service = mock[TestDAO]//problem on injecting DatabaseConfigProvider
val controller = new ExampleCtrl(service)
//service has null value for DatabaseConfigProvider properties
"testMethod()" should {
"return JSON" in {
when(service.exampleMethod) thenReturn "json data"
val result: Future[Result] =
controller.testMethod().apply(FakeRequest())
.withJsonBody(JSON.json("""[{"test":"test"}]"""))
contentAsString(result) mustEqual """[{"test":"test"}]"""
}
}
}
所以我尝试重现该问题,但在修复了 IDE 代码识别的一些问题(例如缺少括号)后,测试通过了。
problem on injecting DatabaseConfigProvider
我在这里没有看到任何问题,因为代码正在通过。从编码人员的角度来看,mock[TestDAO]
实际上并没有实例化一个真正的 TestDAO
,但它创建了一些看起来像一个(接口方面)的东西,但实际上并不包含任何你想要的逻辑里面写着TestDAO
。因此,模拟对象也不需要注入DatabaseConfigProvider
。
service has null value for DatabaseConfigProvider properties
因为服务(您的模拟 TestDAO)是一个模拟,所以这不是问题,因为没有逻辑会使用它。您的模拟实际执行的唯一逻辑在这里:
when(service.exampleMethod) thenReturn "json data"
使用模拟时,您需要编写您希望它们在测试中展示的行为,就像您在上面的代码片段中所做的那样。
如果您想 运行 任何 DatabaseConfigProvider
方法,也许您需要:
- 直接创建一个(例如
val myProvider = [new] DatabaseConfigProvider(...)
),
- 将 mocking 移出一层,这样你就有了一个真正的控制器,一个真正的
TestDAO
和一个 mock DatabaseConfigProvider
(类似于 val controller = new ExampleCtrl(new TestDAO(mock[DatabaseConfigProvider]))
),或者
- 一起编写不同类型的测试。
我通过以下方式解决了问题。
def testDAO (implicit app: Application) = {
val app2testDAO = Application.instanceCache[TestDAO ]
app2testDAO(app)
}
val controller = new ExampleCtrl(testDAO)
我看到了这个帖子
控制器
@Singleton
class ExampleCtrl @Inject() (dao: TestDAO) extends Controller {
//code here
def testMethod = Action { request =>
dao.exampleMethod()
Ok(Json.obj("test" -> "test")
}
}
DAO
class TestDAO @Inject()(protected val provider: DatabaseConfigProvider){
def exampleMethod()
}
测试
class ExampleCtrlSpec extends PlaySpec with MockitoSugar {
val service = mock[TestDAO]//problem on injecting DatabaseConfigProvider
val controller = new ExampleCtrl(service)
//service has null value for DatabaseConfigProvider properties
"testMethod()" should {
"return JSON" in {
when(service.exampleMethod) thenReturn "json data"
val result: Future[Result] =
controller.testMethod().apply(FakeRequest())
.withJsonBody(JSON.json("""[{"test":"test"}]"""))
contentAsString(result) mustEqual """[{"test":"test"}]"""
}
}
}
所以我尝试重现该问题,但在修复了 IDE 代码识别的一些问题(例如缺少括号)后,测试通过了。
problem on injecting DatabaseConfigProvider
我在这里没有看到任何问题,因为代码正在通过。从编码人员的角度来看,mock[TestDAO]
实际上并没有实例化一个真正的 TestDAO
,但它创建了一些看起来像一个(接口方面)的东西,但实际上并不包含任何你想要的逻辑里面写着TestDAO
。因此,模拟对象也不需要注入DatabaseConfigProvider
。
service has null value for DatabaseConfigProvider properties
因为服务(您的模拟 TestDAO)是一个模拟,所以这不是问题,因为没有逻辑会使用它。您的模拟实际执行的唯一逻辑在这里:
when(service.exampleMethod) thenReturn "json data"
使用模拟时,您需要编写您希望它们在测试中展示的行为,就像您在上面的代码片段中所做的那样。
如果您想 运行 任何 DatabaseConfigProvider
方法,也许您需要:
- 直接创建一个(例如
val myProvider = [new] DatabaseConfigProvider(...)
), - 将 mocking 移出一层,这样你就有了一个真正的控制器,一个真正的
TestDAO
和一个 mockDatabaseConfigProvider
(类似于val controller = new ExampleCtrl(new TestDAO(mock[DatabaseConfigProvider]))
),或者 - 一起编写不同类型的测试。
我通过以下方式解决了问题。
def testDAO (implicit app: Application) = {
val app2testDAO = Application.instanceCache[TestDAO ]
app2testDAO(app)
}
val controller = new ExampleCtrl(testDAO)