使用 Mockito 测试 firebase 登录时出错

Error testing firebase login with Mockito

我有使用 firebase 登录用户的登录表单,我正在尝试通过编写一些代码来测试登录功能,我使用 Mockito 来模拟 firebase class 但对于某些人来说它一直失败并且我觉得有问题,如果有人可以帮助解决这个问题,谢谢

@RunWith(AndroidJUnit4ClassRunner::class)
class LoginActivityTest {

    @get:Rule
    var scenario = ActivityScenarioRule(LoginActivity::class.java)
    private lateinit var emailEditText : TextInputLayout
    private lateinit var passwordEditText : TextInputLayout
    private lateinit var firebaseUser: FirebaseUser



 @Test
    fun testCaseRealUserLogin(){

        scenario.scenario.onActivity { it ->
            emailEditText = it.findViewById(R.id.loginEmail)
            passwordEditText = it.findViewById(R.id.loginPassword)
        }

        Looper.prepare()
        emailEditText.editText!!.setText("xxxxxx@gmail.com")
        passwordEditText.editText!!.setText("xxxxxx")

        onView(withId(R.id.loginBtn)).perform(click())

        //Mocking firebase
        val firebaseMock  = mock(FirebaseAuth::class.java)
        `when`(firebaseMock.signInWithEmailAndPassword("xxxxxxx","xxxxxxx"))
            .thenReturn(notNull())

        firebaseUser = firebaseMock.currentUser!!

        assertNotNull(firebaseUser)

    }
}

简单的回答。 activity 没有使用模拟的 class!!。它使用真实的 FirebaseAuth.

因此您需要将模拟的 class 提供给 activity。

简单的方法是 ServiceLocator 模式

先创建一个ServiceLocator.ktclass

object ServiceLocator {

    var auth = Firebase.auth

}

并在生产代码中使用它而不是实例化 auth 对象

// in activity to sign in
ServiceLocator.auth.createUserWithEmailAndPassword(email, password)

其次你需要在测试时用模拟的class替换真实的

fun testCaseRealUserLogin(){

    scenario.scenario.onActivity { it ->
        emailEditText = it.findViewById(R.id.loginEmail)
        passwordEditText = it.findViewById(R.id.loginPassword)
    }

    Looper.prepare()
    emailEditText.editText!!.setText("xxxxxx@gmail.com")
    passwordEditText.editText!!.setText("xxxxxx")

    //Mocking firebase
    val firebaseMock  = mock(FirebaseAuth::class.java)
    // make activity using the mocked class here ---------------
    ServiceLocator.auth = firebaseMock

    onView(withId(R.id.loginBtn)).perform(click())

    // this assertion will pass
    `when`(firebaseMock.signInWithEmailAndPassword("xxxxxxx","xxxxxxx"))
        .thenReturn(notNull())

    firebaseUser = firebaseMock.currentUser!!

    // NOTE: this assertion will fail as the mocked class will always return null and not the actual value
    assertNotNull(firebaseUser)

}