所以,我的一个单元测试中有一个问题。它以绿灯完成,但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
时。我不知道为什么会出现错误。
答案 0 :(得分:2)
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>>())
它应该是好的。