单元测试通过,但有错误

时间:2018-02-07 15:46:36

标签: android unit-testing firebase-authentication

所以,我的一个单元测试中有一个问题。它以绿灯完成,但ClassCastException发生。我要测试的类看起来像这样:

@Singleton
class AuthManager @Inject constructor(val fireBaseAuth: FirebaseAuth) : AuthContract {

    companion object {
        const val SIGN_IN_SUCCEED = "SIGN_IN_SUCCEED"
        const val UNKNOWN_ERROR = "UNKNOWN_ERROR"
    }

    override fun signIn(email: String, password: String): Single<Result> {
        Timber.d("Email: $email, password: $password")
        return Single.create({ emitter ->
            fireBaseAuth.signInWithEmailAndPassword(email, password)
                    .addOnCompleteListener {
                        if (it.isSuccessful) {
                            emitter.onSuccess(Result(isSucceed = true, code = SIGN_IN_SUCCEED))
                            Timber.d("Sign in by email and password succeed")
                        } else {
                            val exception = it.exception as FirebaseAuthException?
                            val result = handleSignInException(exception)
                            emitter.onSuccess(result)
                            Timber.d("Sign in by email and password returned error: " +
                                    result.code)
                        }
                    }
        })
    }

    private fun handleSignInException(exception: FirebaseAuthException?): Result {
        if (exception == null) {
            return Result(isSucceed = false, code = UNKNOWN_ERROR)
        }
        return Result(isSucceed = false, code = exception.errorCode)
    }
}

我对单元测试的提议看起来像这样:

class AuthManagerTest {

        @Mock
        private lateinit var fireBaseAuth: FirebaseAuth

        @Mock
        private lateinit var authResult: Task<AuthResult>

        private lateinit var authManager: AuthManager

        private val EMAIL = "email@email.email"
        private val PASSWORD = "password"

        @Before
        fun setupAuthManager() {
            MockitoAnnotations.initMocks(this)
            authManager = AuthManager(fireBaseAuth)
        }

        @Test
        fun signInByEmailAndPasswordWithSuccessThenCheckIfResultSucceeds() {
            whenever(authResult.isSuccessful).thenReturn(true)
            whenever(fireBaseAuth.signInWithEmailAndPassword(EMAIL, PASSWORD)).thenReturn(authResult)
            doAnswer{
                val listener = it.arguments[0] as OnCompleteListener<AuthResult>
                listener.onComplete(authResult)
            }.`when`(authResult)
                    .addOnCompleteListener(ArgumentMatchers.any<OnCompleteListener<AuthResult>>())
            val expectedResult = Result(isSucceed = true, code = AuthManager.SIGN_IN_SUCCEED)

            val testObserver = authManager.signIn(EMAIL, PASSWORD)
                    .test()
            testObserver.awaitTerminalEvent()

            testObserver
                    .assertNoErrors()
                    .assertValue(expectedResult)
        }
    }

错误:

  

io.reactivex.exceptions.UndeliverableException:   java.lang.ClassCastException:kotlin.Unit无法强制转换为   com.google.android.gms.tasks.Task at   io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:366)at at   io.reactivex.internal.operators.single.SingleCreate $ Emitter.onError(SingleCreate.java:97)     在   io.reactivex.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:42)     在io.reactivex.Single.subscribe(Single.java:2693)at   io.reactivex.Single.test(Single.java:3104)at   bla.bla.bla.AuthManagerTest.signInByEmailAndPasswordWithSuccessThenCheckIfResultSucceeds(AuthManagerTest.kt:48)

48行是在test()上调用testObserver时。我不知道为什么会出现错误。

1 个答案:

答案 0 :(得分:2)

我们来看看MockitoAnswer界面:

public interface Answer<T> {
    /**
     * @return the value to be returned
     */
    T answer(InvocationOnMock invocation) throws Throwable;
}

正如您所见,answer方法返回对象

在您的代码中:

doAnswer{
    val listener = it.arguments[0] as OnCompleteListener<AuthResult>
    listener.onComplete(authResult)
}.`when`(authResult).addOnCompleteListener(ArgumentMatchers.any<OnCompleteListener<AuthResult>>())

answer不返回任何内容,默认情况下,Kotlin表示返回Unit

Task#addOnCompleteListener中返回Task。把它写成:

doAnswer{
        val listener = it.arguments[0] as OnCompleteListener<AuthResult>
        listener.onComplete(authResult)
        authResult
}.`when`(authResult).addOnCompleteListener(ArgumentMatchers.any<OnCompleteListener<AuthResult>>())

它应该是好的。