Loading app/build.gradle +2 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ android { testOptions { unitTests { includeAndroidResources = true returnDefaultValues = true } } } Loading Loading @@ -262,4 +263,5 @@ dependencies { testImplementation 'org.mockito:mockito-core:5.0.0' testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0' testImplementation 'org.robolectric:robolectric:4.9' testImplementation 'org.json:json:20180813' // Added to avoid SystemInfoProvider.getAppBuildInfo() mock error } app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt +5 −9 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import foundation.e.apps.domain.login.usecase.UserLoginUseCase import foundation.e.apps.ui.parentFragment.LoadingViewModel import foundation.e.apps.utils.Resource import foundation.e.apps.utils.SystemInfoProvider import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import java.util.Properties import javax.inject.Inject Loading Loading @@ -145,15 +147,9 @@ class LoginViewModel @Inject constructor( val loginState: LiveData<LoginState> = _loginState fun authenticateAnonymousUser( properties: Properties, userAgent: String = SystemInfoProvider.getAppBuildInfo() ) { fun authenticateAnonymousUser() { viewModelScope.launch { userLoginUseCase( properties = properties, userAgent = userAgent ).also { result -> userLoginUseCase.anonymousUser().onEach {result -> when (result) { is Resource.Success -> { _loginState.value = LoginState(isLoggedIn = true) Loading @@ -167,7 +163,7 @@ class LoginViewModel @Inject constructor( _loginState.value = LoginState(isLoading = true) } } } }.collect() } } } app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt +14 −33 Original line number Diff line number Diff line Loading @@ -16,11 +16,9 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.presentation.login import androidx.arch.core.executor.testing.InstantTaskExecutorRule import foundation.e.apps.testAnonymousRequestBodyData import foundation.e.apps.data.login.LoginSourceRepository import foundation.e.apps.domain.login.usecase.UserLoginUseCase import foundation.e.apps.loginFailureMessage Loading @@ -29,6 +27,7 @@ import foundation.e.apps.util.getOrAwaitValue import foundation.e.apps.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.runTest Loading @@ -42,14 +41,13 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) class LoginViewModelTest { private val testDispatcher = StandardTestDispatcher() @get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule() val rule = InstantTaskExecutorRule() @Mock lateinit var mockUserLoginUseCase: UserLoginUseCase Loading @@ -65,16 +63,11 @@ class LoginViewModelTest { @Test fun testOnSuccessReturnLogInStateTrue() = runTest { Mockito.`when`(mockUserLoginUseCase.invoke( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent )).thenReturn(Resource.Success(testAnonymousResponseData)) Mockito.`when`(mockUserLoginUseCase.anonymousUser()) .thenReturn(flowOf(Resource.Success(testAnonymousResponseData))) val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) loginViewModel.authenticateAnonymousUser( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent ) loginViewModel.authenticateAnonymousUser() testDispatcher.scheduler.advanceUntilIdle() val result = loginViewModel.loginState.getOrAwaitValue() Assert.assertEquals(true, result.isLoggedIn) Loading @@ -83,16 +76,11 @@ class LoginViewModelTest { @Test fun testOnFailureReturnLogInStateFalseWithError() = runTest { Mockito.`when`(mockUserLoginUseCase.invoke( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent )).thenReturn(Resource.Error(loginFailureMessage)) Mockito.`when`(mockUserLoginUseCase.anonymousUser()) .thenReturn(flowOf(Resource.Error(loginFailureMessage, null))) val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) loginViewModel.authenticateAnonymousUser( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent ) loginViewModel.authenticateAnonymousUser() testDispatcher.scheduler.advanceUntilIdle() val result = loginViewModel.loginState.getOrAwaitValue() Assert.assertEquals(false, result.isLoggedIn) Loading @@ -102,16 +90,11 @@ class LoginViewModelTest { @Test fun testOnLoadingReturnLogInStateFalse() = runTest { Mockito.`when`(mockUserLoginUseCase.invoke( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent )).thenReturn(Resource.Loading()) Mockito.`when`(mockUserLoginUseCase.anonymousUser()) .thenReturn(flowOf(Resource.Loading(null))) val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) loginViewModel.authenticateAnonymousUser( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent ) loginViewModel.authenticateAnonymousUser() testDispatcher.scheduler.advanceUntilIdle() val result = loginViewModel.loginState.getOrAwaitValue() Assert.assertEquals(true, result.isLoading) Loading @@ -122,6 +105,4 @@ class LoginViewModelTest { fun tearDown() { Dispatchers.resetMain() } } app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.ktdeleted 100644 → 0 +0 −87 Original line number Diff line number Diff line /* * Copyright MURENA SAS 2023 * Apps Quickly and easily install Android apps onto your device! * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.usecase.repository import android.content.Context import androidx.test.core.app.ApplicationProvider import kotlinx.coroutines.test.runTest import org.junit.Assert import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations import org.robolectric.RobolectricTestRunner import foundation.e.apps.domain.login.repository.LoginRepositoryImpl import foundation.e.apps.testAnonymousRequestBodyData import foundation.e.apps.testAnonymousResponseData import app.lounge.login.anonymous.AnonymousUser import app.lounge.networking.NetworkResult import foundation.e.apps.loginFailureMessage import foundation.e.apps.testFailureException @RunWith(RobolectricTestRunner::class) class LoginRepositoryTest { @Mock lateinit var anonymousUser: AnonymousUser private lateinit var instrumentationContext: Context @Before fun setUp() { MockitoAnnotations.openMocks(this) instrumentationContext= ApplicationProvider.getApplicationContext<Context>() } @Test fun testOnSuccessReturnAuthData() = runTest { Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) .thenReturn(NetworkResult.Success(testAnonymousResponseData)) val result = LoginRepositoryImpl(anonymousUser, instrumentationContext) .run { anonymousUser(testAnonymousRequestBodyData) } Assert.assertNotNull(result) Assert.assertEquals("eOS@murena.io", result.email) } @Test fun testOnFailureReturnErrorWithException() = runTest { Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) .thenReturn(NetworkResult.Error( exception = testFailureException, code = 1, errorMessage = loginFailureMessage )) runCatching { LoginRepositoryImpl(anonymousUser, instrumentationContext) .run { anonymousUser(testAnonymousRequestBodyData) } }.onFailure { error -> Assert.assertEquals(testFailureException.message, error.message) } } } Loading
app/build.gradle +2 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ android { testOptions { unitTests { includeAndroidResources = true returnDefaultValues = true } } } Loading Loading @@ -262,4 +263,5 @@ dependencies { testImplementation 'org.mockito:mockito-core:5.0.0' testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0' testImplementation 'org.robolectric:robolectric:4.9' testImplementation 'org.json:json:20180813' // Added to avoid SystemInfoProvider.getAppBuildInfo() mock error }
app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt +5 −9 Original line number Diff line number Diff line Loading @@ -29,6 +29,8 @@ import foundation.e.apps.domain.login.usecase.UserLoginUseCase import foundation.e.apps.ui.parentFragment.LoadingViewModel import foundation.e.apps.utils.Resource import foundation.e.apps.utils.SystemInfoProvider import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import java.util.Properties import javax.inject.Inject Loading Loading @@ -145,15 +147,9 @@ class LoginViewModel @Inject constructor( val loginState: LiveData<LoginState> = _loginState fun authenticateAnonymousUser( properties: Properties, userAgent: String = SystemInfoProvider.getAppBuildInfo() ) { fun authenticateAnonymousUser() { viewModelScope.launch { userLoginUseCase( properties = properties, userAgent = userAgent ).also { result -> userLoginUseCase.anonymousUser().onEach {result -> when (result) { is Resource.Success -> { _loginState.value = LoginState(isLoggedIn = true) Loading @@ -167,7 +163,7 @@ class LoginViewModel @Inject constructor( _loginState.value = LoginState(isLoading = true) } } } }.collect() } } }
app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt +14 −33 Original line number Diff line number Diff line Loading @@ -16,11 +16,9 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.presentation.login import androidx.arch.core.executor.testing.InstantTaskExecutorRule import foundation.e.apps.testAnonymousRequestBodyData import foundation.e.apps.data.login.LoginSourceRepository import foundation.e.apps.domain.login.usecase.UserLoginUseCase import foundation.e.apps.loginFailureMessage Loading @@ -29,6 +27,7 @@ import foundation.e.apps.util.getOrAwaitValue import foundation.e.apps.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.runTest Loading @@ -42,14 +41,13 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations @OptIn(ExperimentalCoroutinesApi::class) class LoginViewModelTest { private val testDispatcher = StandardTestDispatcher() @get:Rule val instantTaskExecutorRule = InstantTaskExecutorRule() val rule = InstantTaskExecutorRule() @Mock lateinit var mockUserLoginUseCase: UserLoginUseCase Loading @@ -65,16 +63,11 @@ class LoginViewModelTest { @Test fun testOnSuccessReturnLogInStateTrue() = runTest { Mockito.`when`(mockUserLoginUseCase.invoke( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent )).thenReturn(Resource.Success(testAnonymousResponseData)) Mockito.`when`(mockUserLoginUseCase.anonymousUser()) .thenReturn(flowOf(Resource.Success(testAnonymousResponseData))) val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) loginViewModel.authenticateAnonymousUser( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent ) loginViewModel.authenticateAnonymousUser() testDispatcher.scheduler.advanceUntilIdle() val result = loginViewModel.loginState.getOrAwaitValue() Assert.assertEquals(true, result.isLoggedIn) Loading @@ -83,16 +76,11 @@ class LoginViewModelTest { @Test fun testOnFailureReturnLogInStateFalseWithError() = runTest { Mockito.`when`(mockUserLoginUseCase.invoke( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent )).thenReturn(Resource.Error(loginFailureMessage)) Mockito.`when`(mockUserLoginUseCase.anonymousUser()) .thenReturn(flowOf(Resource.Error(loginFailureMessage, null))) val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) loginViewModel.authenticateAnonymousUser( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent ) loginViewModel.authenticateAnonymousUser() testDispatcher.scheduler.advanceUntilIdle() val result = loginViewModel.loginState.getOrAwaitValue() Assert.assertEquals(false, result.isLoggedIn) Loading @@ -102,16 +90,11 @@ class LoginViewModelTest { @Test fun testOnLoadingReturnLogInStateFalse() = runTest { Mockito.`when`(mockUserLoginUseCase.invoke( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent )).thenReturn(Resource.Loading()) Mockito.`when`(mockUserLoginUseCase.anonymousUser()) .thenReturn(flowOf(Resource.Loading(null))) val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) loginViewModel.authenticateAnonymousUser( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent ) loginViewModel.authenticateAnonymousUser() testDispatcher.scheduler.advanceUntilIdle() val result = loginViewModel.loginState.getOrAwaitValue() Assert.assertEquals(true, result.isLoading) Loading @@ -122,6 +105,4 @@ class LoginViewModelTest { fun tearDown() { Dispatchers.resetMain() } }
app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.ktdeleted 100644 → 0 +0 −87 Original line number Diff line number Diff line /* * Copyright MURENA SAS 2023 * Apps Quickly and easily install Android apps onto your device! * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. */ package foundation.e.apps.usecase.repository import android.content.Context import androidx.test.core.app.ApplicationProvider import kotlinx.coroutines.test.runTest import org.junit.Assert import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations import org.robolectric.RobolectricTestRunner import foundation.e.apps.domain.login.repository.LoginRepositoryImpl import foundation.e.apps.testAnonymousRequestBodyData import foundation.e.apps.testAnonymousResponseData import app.lounge.login.anonymous.AnonymousUser import app.lounge.networking.NetworkResult import foundation.e.apps.loginFailureMessage import foundation.e.apps.testFailureException @RunWith(RobolectricTestRunner::class) class LoginRepositoryTest { @Mock lateinit var anonymousUser: AnonymousUser private lateinit var instrumentationContext: Context @Before fun setUp() { MockitoAnnotations.openMocks(this) instrumentationContext= ApplicationProvider.getApplicationContext<Context>() } @Test fun testOnSuccessReturnAuthData() = runTest { Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) .thenReturn(NetworkResult.Success(testAnonymousResponseData)) val result = LoginRepositoryImpl(anonymousUser, instrumentationContext) .run { anonymousUser(testAnonymousRequestBodyData) } Assert.assertNotNull(result) Assert.assertEquals("eOS@murena.io", result.email) } @Test fun testOnFailureReturnErrorWithException() = runTest { Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) .thenReturn(NetworkResult.Error( exception = testFailureException, code = 1, errorMessage = loginFailureMessage )) runCatching { LoginRepositoryImpl(anonymousUser, instrumentationContext) .run { anonymousUser(testAnonymousRequestBodyData) } }.onFailure { error -> Assert.assertEquals(testFailureException.message, error.message) } } }