Модульный тест зависает в Android при тестировании функции приостановки - PullRequest
0 голосов
/ 16 июня 2020

У меня есть функция приостановки на уровне репозитория моего приложения. Я пытаюсь выполнить модульное тестирование функции, но каждый раз, когда она выполняется, кажется, что она зависает при вызове await(), а затем просто остается там навсегда и никогда не завершается. Похоже, что в фоновом режиме происходит какая-то тупиковая ситуация, но не сразу видно, что происходит.

Есть ли здесь какие-нибудь решения?

Вот моя функция репо:

suspend fun login(email: String, password: String): DataState<AuthViewState> {
        try {
            val authResult = firebaseAuth
                .signInWithEmailAndPassword(email, password)
                .await()

            return DataState.data<AuthViewState>(
                data = AuthViewState(
                    authResult.user?.uid
                )
            )
        } catch (e: FirebaseAuthInvalidUserException) {
            Log.e(TAG, "loginUserIfExisting: FirebaseAuthInvalidUserException: ", e)
            return DataState.error<AuthViewState>(
                "User not found. Please register."
            )
        } catch (e: FirebaseAuthInvalidCredentialsException) {
            Log.e(TAG, "loginUserIfExisting: FirebaseAuthInvalidCredentialsException: ", e)
            return DataState.error<AuthViewState>(
                "Your password/email is incorrect. Please try again."
            )
        }
    }

А вот и мой тест с моками:

@RunWith(JUnit4::class)
class AuthRepositoryTest {

    private val email = "lee.a.wilson90@gmail.com"
    private val password = "fakepassword"
    private val CORRECT_USER_ID = "CORRECT_USER_ID"

    private lateinit var SUT: AuthRepository

    @Mock
    private lateinit var firebaseAuth: FirebaseAuth

    @Mock
    private lateinit var authResultTask: Task<AuthResult>

    @Mock
    private lateinit var mockResult: AuthResult

    @Mock
    private lateinit var mockFirebaseUser: FirebaseUser

    @Mock
    private lateinit var mockUserPropertiesDao: UserPropertiesDao

    @Mock
    private lateinit var mockSharedPreferences: SharedPreferences

    @Mock
    private lateinit var mockSharedPreferencesEditor: SharedPreferences.Editor

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)

        `when`(firebaseAuth.signInWithEmailAndPassword(email, password))
            .thenReturn(authResultTask)

        `when`(mockResult.user)
            .thenReturn(mockFirebaseUser)

        `when`(mockFirebaseUser.uid)
            .thenReturn("CORRECT_USER_ID")

        `when`(mockUserPropertiesDao.searchByEmail(email))
            .thenReturn(null)

        `when`(mockSharedPreferences.getString(Constants.PREVIOUS_AUTH_USER, null))
            .thenReturn(null)

        SUT = AuthRepository(
            firebaseAuth,
            mockUserPropertiesDao,
            mockSharedPreferences,
            mockSharedPreferencesEditor
        )
    }

    @Test
    fun test_correctCredentialsEntered_correctOutputState() = runBlocking {
        whenever(authResultTask.await()).thenReturn(mockResult)
        val resultState = SUT.login(email, password)
        val result = resultState.data!!.getContentIfNotHandled()!!.uid
        assertEquals(CORRECT_USER_ID, result)
    }
}

1 Ответ

0 голосов
/ 16 июня 2020

Похоже, что Mockito еще не поддерживает функции приостановки.

Поэтому вместо насмешки над authResultTask: Task<AuthResult> (что я считаю плохой идеей) вы должны использовать TaskCompletionSource<AuthResult> и установите результат.

EDIT:

Чтобы завершить этот ответ, объяснив наблюдаемое поведение.

Модульный тест зависает, потому что Continuation<T>.resume() isn 'не вызывается mockito, когда вы имитируете функцию await().

...