0

I have made a simple unit test which tests a coroutines function which uses firebase. I've mocked all the dependencies and the methods being used in this function I'm testing, but it continues to hang. I'm not sure exactly where it's hanging, but I would assume on the mocking of firestore, and it has await().

Test Class:


import android.content.Context
import com.example.socialtoker.data.db.UserDao
import com.example.socialtoker.data.repository.UserDataRepository
import com.example.socialtoker.data.repository.UserDataRepositoryImpl
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.DatabaseReference
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.storage.FirebaseStorage
import io.mockk.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4

@RunWith(JUnit4::class)
@ExperimentalCoroutinesApi
class UserDataRepositoryImplTest {

    private val contextMock = mockk<Context>{
        every { getExternalFilesDir(any())?.absolutePath } returns "src/SocialToker/"
    }
    private val firestoreMock = mockk<FirebaseFirestore>{
        coEvery { collection("Users").document(any()).set(any()).await() } returns mockk()
    }
    private val firebaseAuthMock = mockk<FirebaseAuth>{
        coEvery { createUserWithEmailAndPassword(any(), any()) } returns mockk()
        every { currentUser?.uid } returns "UID"
    }
    private val firebaseStorageMock = mockk<FirebaseStorage>()
    private val firebaseDatabaseMock = mockk<DatabaseReference>()
    private val daoMock = mockk<UserDao>{
        coEvery { addUser(any()) } returns mockk()
    }

    private lateinit var userDateRepository: UserDataRepository

    private val emailAddress = "socialtoker@socialtoker.com"
    private val password = "socialtokerpassword"
    private val username = "socialtoker"



    @Before
    fun setup() {
        userDateRepository = UserDataRepositoryImpl(
            contextMock,
            firestoreMock,
            firebaseAuthMock,
            firebaseStorageMock,
            firebaseDatabaseMock,
            daoMock
        )
    }

    @Test
    fun `createUser calls firebase and stores user info locally and remotely`() = runBlocking {
        // WHEN
        userDateRepository.createUser(emailAddress, password, username)

        //THEN
        coVerify { firebaseAuthMock.createUserWithEmailAndPassword(emailAddress, password) }
    }


}

Test Subject:

    override suspend fun createUser(email: String, password: String, username: String): AuthResult {
        try {
            val data = hashMapOf(
                "name" to username
            )
            val authResult = firebaseAuth.createUserWithEmailAndPassword(email, password).await()
            val uid = firebaseAuth.currentUser!!.uid
            userDao.addUser(UserData(uid, username, "", ""))
            firestoreRef.collection("Users")
                .document(uid)
                .set(data).await()
            return authResult
        } catch (error: Throwable) {
            throw RepositoryError(
                error.localizedMessage ?: "Unable to create user", error
            )
        }
    }
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Lloyd Hussell
  • 55
  • 1
  • 7
  • If nobody can help with this, I am half tempted to just take a slightly different approach by extracting the firebase calls and my local dao calls into their own respective repos which will be called from my main repo. – Lloyd Hussell Jan 01 '22 at 15:43

1 Answers1

1

Please note that await is an extension function on Task class. Therefore Mocking extension functions might need to be taken into consideration.

PGliw
  • 311
  • 4
  • 9