使用 firebase 数据库抛出错误进行测试
test with firebase database throwing error
我在我的项目中使用 firebase,我正在测试包括 firebase 组件在内的所有功能,我最近尝试测试 firebase 数据库,但它抛出了一个错误,我无法理解是否有人可以提供帮助,我将不胜感激,谢谢
- 我遇到的错误
Attempt to invoke virtual method 'com.google.firebase.database.DatabaseReference com.google.firebase.database.DatabaseReference.child(java.lang.String)' on a null object reference
at com.revert.journey.app.chatui.ChatHomeActivityTest.testCaseSendMessage
- 这是我的测试代码
@Test
fun testCaseSendMessage(){
val databaseMock = mock(DatabaseReference::class.java)
ServiceLocator.reference = databaseMock
`when`(databaseMock.child("Messages").child("1251515").setValue(Utils.message()))
.thenReturn(isNotNull())
}
- 这是我的真实代码
val messageMap = hashMapOf<String,Any>()
messageMap["userName"] = userName
messageMap["userMessage"] = message
messageMap["userPic"] = userPic
messageMap["messageTiming"] = Calendar.getInstance().timeInMillis.toString()
messageMap["chatImage"] = downloadUrl
messageMap["uid"] = firebaseAuth.currentUser!!.uid
ServiceLocator.reference
.child("Messages")
.child(System.currentTimeMillis().toString())
.setValue(messageMap).await()
- 服务定位器class
object ServiceLocator {
var firebaseAuth = FirebaseAuth.getInstance()
var reference = FirebaseDatabase.getInstance().reference
}
- 来自我的 firebase 的图像示例
- 更新
var base = ServiceLocator.reference.child("Messages")
var child = base.child(System.currentTimeMillis().toString())
child.setValue(messageMap).await()
如果你想模拟完整的调用链,你可以像这样为中间状态创建模拟(我不知道这里用于实时数据库的所有正确类型,但类似的方法适用于 Firestore)
val databaseMock = mock(DatabaseReference::class.java)
val childMock = mock(Reference::class.java)
val mockTask = mock(??) // set type to whatever "setValue" returns
doReturn(childMock).`when`(databaseMock).child(anyString())
doReturn(childMock).`when`(childMock).child(anyString())
doReturn(mockTask).`when`(childMock).setValue(any())
如果您想实际测试是否设置了正确的值,您可以向 mock 添加一个侦听器以拦截传递给它的实际值
doAnswer { invocation ->
val args = invocation.arguments
val l = args[0] as Map<String,Any>
//add tests here to assert that the map values you sent are correct
null
}.`when`(childMock).setValue(any())
调试技巧
如果您想诊断在这种情况下发生了什么,您可以将真实代码中的链式调用更改为类似于下面的代码。然后,如果调用之一 returns null 您将确切知道它是哪一个,并且可以为其添加缺少的模拟。
val db = ServiceLocator.reference
val cm = db.child("Messages")
val ct = cm.child(System.currentTimeMillis().toString())
val response = ct.setValue(messageMap)
response.await()
None 这些调用应该在测试中访问您的数据库,因此实际的数据库模式无关紧要。重要的是正确设置模拟(因为无论如何你都在使用模拟数据库)
我在我的项目中使用 firebase,我正在测试包括 firebase 组件在内的所有功能,我最近尝试测试 firebase 数据库,但它抛出了一个错误,我无法理解是否有人可以提供帮助,我将不胜感激,谢谢
- 我遇到的错误
Attempt to invoke virtual method 'com.google.firebase.database.DatabaseReference com.google.firebase.database.DatabaseReference.child(java.lang.String)' on a null object reference
at com.revert.journey.app.chatui.ChatHomeActivityTest.testCaseSendMessage
- 这是我的测试代码
@Test
fun testCaseSendMessage(){
val databaseMock = mock(DatabaseReference::class.java)
ServiceLocator.reference = databaseMock
`when`(databaseMock.child("Messages").child("1251515").setValue(Utils.message()))
.thenReturn(isNotNull())
}
- 这是我的真实代码
val messageMap = hashMapOf<String,Any>()
messageMap["userName"] = userName
messageMap["userMessage"] = message
messageMap["userPic"] = userPic
messageMap["messageTiming"] = Calendar.getInstance().timeInMillis.toString()
messageMap["chatImage"] = downloadUrl
messageMap["uid"] = firebaseAuth.currentUser!!.uid
ServiceLocator.reference
.child("Messages")
.child(System.currentTimeMillis().toString())
.setValue(messageMap).await()
- 服务定位器class
object ServiceLocator {
var firebaseAuth = FirebaseAuth.getInstance()
var reference = FirebaseDatabase.getInstance().reference
}
- 来自我的 firebase 的图像示例
- 更新
var base = ServiceLocator.reference.child("Messages")
var child = base.child(System.currentTimeMillis().toString())
child.setValue(messageMap).await()
如果你想模拟完整的调用链,你可以像这样为中间状态创建模拟(我不知道这里用于实时数据库的所有正确类型,但类似的方法适用于 Firestore)
val databaseMock = mock(DatabaseReference::class.java)
val childMock = mock(Reference::class.java)
val mockTask = mock(??) // set type to whatever "setValue" returns
doReturn(childMock).`when`(databaseMock).child(anyString())
doReturn(childMock).`when`(childMock).child(anyString())
doReturn(mockTask).`when`(childMock).setValue(any())
如果您想实际测试是否设置了正确的值,您可以向 mock 添加一个侦听器以拦截传递给它的实际值
doAnswer { invocation ->
val args = invocation.arguments
val l = args[0] as Map<String,Any>
//add tests here to assert that the map values you sent are correct
null
}.`when`(childMock).setValue(any())
调试技巧
如果您想诊断在这种情况下发生了什么,您可以将真实代码中的链式调用更改为类似于下面的代码。然后,如果调用之一 returns null 您将确切知道它是哪一个,并且可以为其添加缺少的模拟。
val db = ServiceLocator.reference
val cm = db.child("Messages")
val ct = cm.child(System.currentTimeMillis().toString())
val response = ct.setValue(messageMap)
response.await()
None 这些调用应该在测试中访问您的数据库,因此实际的数据库模式无关紧要。重要的是正确设置模拟(因为无论如何你都在使用模拟数据库)