kotlin 使用JUnit4检测到未完成的存根

trnvg8h3  于 2023-05-29  发布在  Kotlin
关注(0)|答案(1)|浏览(296)

我正在使用JUnit4和Mockito测试我的身份验证类。我写了以下简单的测试类:

@ExperimentalCoroutinesApi
class FirebaseAuthenticationDataSourceTest {
    @get:Rule
    val mockitoRule: MockitoRule = MockitoJUnit.rule()

    @get:Rule
    val instantTaskExecutorRule = InstantTaskExecutorRule()

    @Mock
    var mockAuth: FirebaseAuth = mock()

    @Mock
    lateinit var mockSharedPref: SharedPreferences

    @InjectMocks
    lateinit var dataSource: FirebaseAuthenticationDataSource

    @Before
    fun setup() {
        // Inizializza i mock e il data source prima di ogni test
        MockitoAnnotations.openMocks(this)
    }

    @Test
    fun `signIn success - should emit Success result with user data`() = runTest {
        // Mock il comportamento di FirebaseAuth.signInWithEmailAndPassword
        val mockAuthResult = mock<AuthResult>()
        val mockFirebaseUser = mock<FirebaseUser> {
            on { email } doReturn "test@example.com"
            on { uid } doReturn "12345"
            on { displayName } doReturn "Test User"
        }

        // Utilizza when invece di whenever per mockAuth
        `when`(mockAuth.signInWithEmailAndPassword(any(), any())).thenReturn(mockTask(mockAuthResult)) //line 69
        `when`(mockAuthResult.user).thenReturn(mockFirebaseUser)

        // Esegui il metodo signIn del data source
        val signInFlow = dataSource.signIn("test@example.com", "password")

        // Ottieni i risultati dalla flow e verificali
        val results = signInFlow.toList()

        assertEquals(2, results.size)
        assertEquals(Result.Loading, results[0])
        assertEquals(Result.Success(User("test@example.com", "12345", "Test User")), results[1])
    }

    private fun <T> mockTask(result: T): Task<T> {
        val mockTask = mock<Task<T>>()
        whenever(mockTask.isSuccessful).thenReturn(true)
        whenever(mockTask.result).thenReturn(result)
        return mockTask
    }
}

它测试以下方法:

class FirebaseAuthenticationDataSource
@Inject
constructor(
    private val auth: FirebaseAuth,
    private val sharedPref: SharedPreferences
) : AuthDataSource {

    override fun signIn(email: String, password: String): Flow<Result<User>> = flow {
        emit(Result.Loading)
        try {
            val result = auth.signInWithEmailAndPassword(email, password).await()
            emit(
                Result.Success(
                    User(
                        result.user!!.email ?: "",
                        result.user!!.uid,
                        result.user!!.displayName ?: ""
                    )
                )
            )
        } catch (e: Exception) {
            emit(Result.Error(e))
        }
    }
}

在这种情况下,前面的方法必须允许用户使用Firebase作为提供程序登录。
但是当我启动测试时,我得到了这个错误:

Unfinished stubbing detected here:
-> at com.indisparte.loginfeature.data.datasource.FirebaseAuthenticationDataSourceTest$signIn success - should emit Success result with user data$1.invokeSuspend(FirebaseAuthenticationDataSourceTest.kt:69)

E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, which is not supported
 3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed

我不明白错误在哪里,在互联网上搜索,似乎我正在嫁接模拟,但我不明白在哪里。

mwkjh3gx

mwkjh3gx1#

当你测试类的时候,你需要对他使用@InejctMocks。@InjectMocks创建类的示例,并将使用@Mock(或@Spy)注解创建的模拟注入到该示例中。所以换掉这个

@Mock
    lateinit var dataSource: FirebaseAuthenticationDataSource

用这个:

@InjectMocks
    lateinit var dataSource: FirebaseAuthenticationDataSource

相关问题