diff options
| author | David Göransson <david.goransson90@gmail.com> | 2024-01-10 15:04:30 +0100 |
|---|---|---|
| committer | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2024-01-11 09:51:38 +0100 |
| commit | abb2b79a830fbdaa0afa22a5cb2c272fa94a538c (patch) | |
| tree | ecc720997aeb3568b9d02a2c7c099ea220d37c3f | |
| parent | b5decd12a264c3e37092211eb0951dac6c640670 (diff) | |
| download | mullvadvpn-abb2b79a830fbdaa0afa22a5cb2c272fa94a538c.tar.xz mullvadvpn-abb2b79a830fbdaa0afa22a5cb2c272fa94a538c.zip | |
Migrate app unit tests to Junit5
33 files changed, 549 insertions, 553 deletions
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index a49db33415..e7403733d0 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,3 +1,4 @@ +import Dependencies.Plugin.ksp import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties import com.android.build.gradle.internal.tasks.factory.dependsOn import java.io.FileInputStream @@ -10,6 +11,7 @@ plugins { id(Dependencies.Plugin.kotlinAndroidId) id(Dependencies.Plugin.kotlinParcelizeId) id(Dependencies.Plugin.ksp) version Versions.Plugin.ksp + id(Dependencies.Plugin.junit5) version Versions.Plugin.junit5 } val repoRootPath = rootProject.projectDir.absoluteFile.parentFile.absolutePath @@ -349,21 +351,25 @@ dependencies { // Leak canary leakCanaryImplementation(Dependencies.leakCanary) - // Test dependencies + // Needed for createComposeExtension() and createAndroidComposeExtension() + debugImplementation(Dependencies.Compose.uiTestManifest) testImplementation(project(Dependencies.Mullvad.commonTestLib)) testImplementation(Dependencies.Kotlin.test) testImplementation(Dependencies.KotlinX.coroutinesTest) testImplementation(Dependencies.MockK.core) - testImplementation(Dependencies.junit) testImplementation(Dependencies.turbine) + testImplementation(Dependencies.junitApi) + testRuntimeOnly(Dependencies.junitEngine) + testImplementation(Dependencies.junitParams) // UI test dependencies debugImplementation(Dependencies.AndroidX.fragmentTestning) // Fixes: https://github.com/android/android-test/issues/1589 debugImplementation(Dependencies.AndroidX.testMonitor) debugImplementation(Dependencies.Compose.testManifest) - androidTestImplementation(Dependencies.Compose.junit) androidTestImplementation(Dependencies.Koin.test) androidTestImplementation(Dependencies.Kotlin.test) androidTestImplementation(Dependencies.MockK.android) + androidTestImplementation(Dependencies.junitApi) + androidTestImplementation(Dependencies.Compose.junit5) } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt index 30b54cea11..9767d3930a 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt @@ -9,6 +9,7 @@ import kotlin.test.assertEquals import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule import net.mullvad.mullvadvpn.repository.InAppNotification @@ -19,13 +20,13 @@ import net.mullvad.mullvadvpn.usecase.TunnelStateNotificationUseCase import net.mullvad.mullvadvpn.usecase.VersionNotificationUseCase import net.mullvad.talpid.tunnel.ErrorState import org.joda.time.DateTime -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class InAppNotificationControllerTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private lateinit var inAppNotificationController: InAppNotificationController private val accountExpiryNotifications = MutableStateFlow(emptyList<InAppNotification>()) @@ -35,7 +36,7 @@ class InAppNotificationControllerTest { private lateinit var job: Job - @Before + @BeforeEach fun setup() { MockKAnnotations.init(this) @@ -56,11 +57,11 @@ class InAppNotificationControllerTest { newDeviceNotificationUseCase, versionNotificationUseCase, tunnelStateNotificationUseCase, - CoroutineScope(job + testCoroutineRule.testDispatcher) + CoroutineScope(job + UnconfinedTestDispatcher()) ) } - @After + @AfterEach fun teardown() { job.cancel() unmockkAll() diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManagerTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManagerTest.kt index 3e26a37c2c..3296243c56 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManagerTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsIconManagerTest.kt @@ -12,23 +12,23 @@ import io.mockk.unmockkAll import io.mockk.verify import kotlin.test.assertEquals import kotlin.test.assertFails -import org.junit.After -import org.junit.Before -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test class ApplicationsIconManagerTest { private val mockedPackageManager = mockk<PackageManager>() private val mockedMainLooper = mockk<Looper>() private val testSubject = ApplicationsIconManager(mockedPackageManager) - @Before + @BeforeEach fun setUp() { mockkStatic(Looper::class) mockkStatic(DRAWABLE_EXTENSION_CLASS) every { Looper.getMainLooper() } returns mockedMainLooper } - @After + @AfterEach fun tearDown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt index a74ab85fc4..1b37184915 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/applist/ApplicationsProviderTest.kt @@ -8,8 +8,8 @@ import io.mockk.mockk import io.mockk.unmockkAll import io.mockk.verifyAll import net.mullvad.mullvadvpn.lib.common.test.assertLists -import org.junit.After -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Test class ApplicationsProviderTest { private val mockedPackageManager = mockk<PackageManager>() @@ -17,7 +17,7 @@ class ApplicationsProviderTest { private val testSubject = ApplicationsProvider(mockedPackageManager, selfPackageName) private val internet = Manifest.permission.INTERNET - @After + @AfterEach fun tearDown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/relaylist/RelayNameComparatorTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/relaylist/RelayNameComparatorTest.kt index 2ef1d1f02c..dc9c141f28 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/relaylist/RelayNameComparatorTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/relaylist/RelayNameComparatorTest.kt @@ -2,13 +2,13 @@ package net.mullvad.mullvadvpn.relaylist import io.mockk.mockk import io.mockk.unmockkAll -import org.junit.After -import org.junit.Assert.assertTrue -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test class RelayNameComparatorTest { - @After + @AfterEach fun tearDown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxyTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxyTest.kt index 52bbbee0a6..4da6c4fdaf 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxyTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ConnectionProxyTest.kt @@ -19,9 +19,9 @@ import kotlin.test.assertEquals import net.mullvad.mullvadvpn.lib.ipc.Event import net.mullvad.mullvadvpn.lib.ipc.EventDispatcher import net.mullvad.mullvadvpn.lib.ipc.Request -import org.junit.After -import org.junit.Before -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test class ConnectionProxyTest { @@ -32,7 +32,7 @@ class ConnectionProxyTest { @MockK private lateinit var mockedDispatchingHandler: EventDispatcher lateinit var connectionProxy: ConnectionProxy - @Before + @BeforeEach fun setup() { mockkStatic(Looper::class) mockkStatic(Log::class) @@ -44,7 +44,7 @@ class ConnectionProxyTest { every { Log.e(any(), any()) } returns mockk(relaxed = true) } - @After + @AfterEach fun tearDown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSourceTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSourceTest.kt index 50f930d2a5..d4fd349438 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSourceTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionDeviceDataSourceTest.kt @@ -17,9 +17,9 @@ import net.mullvad.mullvadvpn.lib.common.util.JobTracker import net.mullvad.mullvadvpn.lib.ipc.Event import net.mullvad.mullvadvpn.lib.ipc.EventDispatcher import net.mullvad.mullvadvpn.lib.ipc.Request -import org.junit.After -import org.junit.Before -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test class ServiceConnectionDeviceDataSourceTest { private val tracker = JobTracker() @@ -32,7 +32,7 @@ class ServiceConnectionDeviceDataSourceTest { lateinit var serviceConnectionDeviceDataSource: ServiceConnectionDeviceDataSource - @Before + @BeforeEach fun setup() { mockkStatic(Looper::class) mockkStatic(android.util.Log::class) @@ -44,7 +44,7 @@ class ServiceConnectionDeviceDataSourceTest { every { android.util.Log.e(any(), any()) } returns mockk(relaxed = true) } - @After + @AfterEach fun tearDown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/AccountExpiryNotificationUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/AccountExpiryNotificationUseCaseTest.kt index 5341708d3b..f068642bec 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/AccountExpiryNotificationUseCaseTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/AccountExpiryNotificationUseCaseTest.kt @@ -14,18 +14,18 @@ import net.mullvad.mullvadvpn.model.AccountExpiry import net.mullvad.mullvadvpn.repository.AccountRepository import net.mullvad.mullvadvpn.repository.InAppNotification import org.joda.time.DateTime -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class AccountExpiryNotificationUseCaseTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val accountExpiry = MutableStateFlow<AccountExpiry>(AccountExpiry.Missing) private lateinit var accountExpiryNotificationUseCase: AccountExpiryNotificationUseCase - @Before + @BeforeEach fun setup() { MockKAnnotations.init(this) @@ -35,7 +35,7 @@ class AccountExpiryNotificationUseCaseTest { accountExpiryNotificationUseCase = AccountExpiryNotificationUseCase(accountRepository) } - @After + @AfterEach fun teardown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/NewDeviceUseNotificationCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/NewDeviceUseNotificationCaseTest.kt index bd375d729a..5e4403c38d 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/NewDeviceUseNotificationCaseTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/NewDeviceUseNotificationCaseTest.kt @@ -15,13 +15,13 @@ import net.mullvad.mullvadvpn.model.Device import net.mullvad.mullvadvpn.model.DeviceState import net.mullvad.mullvadvpn.repository.DeviceRepository import net.mullvad.mullvadvpn.repository.InAppNotification -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class NewDeviceUseNotificationCaseTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val deviceName = "Frank Zebra" private val deviceState = @@ -32,7 +32,7 @@ class NewDeviceUseNotificationCaseTest { ) private lateinit var newDeviceNotificationUseCase: NewDeviceNotificationUseCase - @Before + @BeforeEach fun setup() { MockKAnnotations.init(this) @@ -42,7 +42,7 @@ class NewDeviceUseNotificationCaseTest { NewDeviceNotificationUseCase(deviceRepository = mockDeviceRepository) } - @After + @AfterEach fun teardown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCaseTest.kt index bdc5ea49b8..6563f7e6e9 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCaseTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCaseTest.kt @@ -16,8 +16,8 @@ import net.mullvad.mullvadvpn.repository.AccountRepository import net.mullvad.talpid.tunnel.ErrorState import net.mullvad.talpid.tunnel.ErrorStateCause import org.joda.time.DateTime -import org.junit.Before -import org.junit.Test +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test class OutOfTimeUseCaseTest { private val mockAccountRepository: AccountRepository = mockk() @@ -28,7 +28,7 @@ class OutOfTimeUseCaseTest { lateinit var outOfTimeUseCase: OutOfTimeUseCase - @Before + @BeforeEach fun setup() { every { mockAccountRepository.accountExpiryState } returns expiry every { mockMessageHandler.events<Event.TunnelStateChange>() } returns events diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/PlayPaymentUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/PlayPaymentUseCaseTest.kt index a1d8bee37a..fb85629a9c 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/PlayPaymentUseCaseTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/PlayPaymentUseCaseTest.kt @@ -12,7 +12,7 @@ import net.mullvad.mullvadvpn.lib.payment.PaymentRepository import net.mullvad.mullvadvpn.lib.payment.model.PaymentAvailability import net.mullvad.mullvadvpn.lib.payment.model.ProductId import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult -import org.junit.Test +import org.junit.jupiter.api.Test class PlayPaymentUseCaseTest { diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCaseTest.kt index e67630642d..244c735ee9 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCaseTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/TunnelStateNotificationUseCaseTest.kt @@ -19,13 +19,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState import net.mullvad.talpid.tunnel.ActionAfterDisconnect import net.mullvad.talpid.tunnel.ErrorState import net.mullvad.talpid.util.EventNotifier -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class TunnelStateNotificationUseCaseTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockServiceConnectionManager: ServiceConnectionManager = mockk() private val mockServiceConnectionContainer: ServiceConnectionContainer = mockk() @@ -37,7 +37,7 @@ class TunnelStateNotificationUseCaseTest { private val eventNotifierTunnelUiState = EventNotifier<TunnelState>(TunnelState.Disconnected()) - @Before + @BeforeEach fun setup() { MockKAnnotations.init(this) every { mockConnectionProxy.onUiStateChange } returns eventNotifierTunnelUiState @@ -49,7 +49,7 @@ class TunnelStateNotificationUseCaseTest { TunnelStateNotificationUseCase(serviceConnectionManager = mockServiceConnectionManager) } - @After + @AfterEach fun teardown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/VersionNotificationUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/VersionNotificationUseCaseTest.kt index 5aba70c938..12f7207280 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/VersionNotificationUseCaseTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/VersionNotificationUseCaseTest.kt @@ -18,13 +18,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState import net.mullvad.mullvadvpn.util.appVersionCallbackFlow -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class VersionNotificationUseCaseTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockServiceConnectionManager: ServiceConnectionManager = mockk() private lateinit var mockAppVersionInfoCache: AppVersionInfoCache @@ -43,7 +43,7 @@ class VersionNotificationUseCaseTest { ) private lateinit var versionNotificationUseCase: VersionNotificationUseCase - @Before + @BeforeEach fun setup() { MockKAnnotations.init(this) mockkStatic(CACHE_EXTENSION_CLASS) @@ -63,7 +63,7 @@ class VersionNotificationUseCaseTest { ) } - @After + @AfterEach fun teardown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/utils/VoucherRegexHelperParameterizedTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/utils/VoucherRegexHelperParameterizedTest.kt index 60db08b85f..1722e81a9d 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/utils/VoucherRegexHelperParameterizedTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/utils/VoucherRegexHelperParameterizedTest.kt @@ -1,34 +1,29 @@ package net.mullvad.mullvadvpn.utils +import java.util.stream.Stream +import kotlin.test.assertEquals import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule import net.mullvad.mullvadvpn.util.VoucherRegexHelper -import org.hamcrest.CoreMatchers.equalTo -import org.hamcrest.MatcherAssert.assertThat -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.Parameterized +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.MethodSource private const val IS_ACCEPTED_FORMAT = true private const val IS_UNACCEPTED_FORMAT = false -@RunWith(Parameterized::class) -class VoucherRegexHelperParameterizedTest( - private val isValid: Boolean, - private val voucher: String -) { - @get:Rule val testCoroutineRule = TestCoroutineRule() +@ExtendWith(TestCoroutineRule::class) +class VoucherRegexHelperParameterizedTest { - @Test - fun testVoucherFormat() { - assertThat(VoucherRegexHelper.validate(voucher), equalTo(isValid)) + @ParameterizedTest + @MethodSource("data") + fun testVoucherFormat(isValid: Boolean, voucher: String) { + assertEquals(VoucherRegexHelper.validate(voucher), isValid) } companion object { @JvmStatic - @Parameterized.Parameters - fun data(): Collection<Array<Any>> = - listOf( + fun data(): Stream<Array<Any>> = + Stream.of( arrayOf(IS_ACCEPTED_FORMAT, "1"), arrayOf(IS_ACCEPTED_FORMAT, "a"), arrayOf(IS_ACCEPTED_FORMAT, "A"), diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt index 22acc97986..637c531039 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt @@ -30,13 +30,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.AuthTokenCache import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.ui.serviceconnection.authTokenCache import net.mullvad.mullvadvpn.usecase.PaymentUseCase -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class AccountViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockAccountRepository: AccountRepository = mockk(relaxUnitFun = true) private val mockServiceConnectionManager: ServiceConnectionManager = mockk() @@ -62,7 +62,7 @@ class AccountViewModelTest { private lateinit var viewModel: AccountViewModel - @Before + @BeforeEach fun setUp() { mockkStatic(CACHE_EXTENSION_CLASS) mockkStatic(PURCHASE_RESULT_EXTENSIONS_CLASS) @@ -82,7 +82,7 @@ class AccountViewModelTest { ) } - @After + @AfterEach fun tearDown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ChangelogViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ChangelogViewModelTest.kt index 3350178ca3..d9a5ae534e 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ChangelogViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ChangelogViewModelTest.kt @@ -12,19 +12,19 @@ import kotlin.test.assertNotNull import kotlinx.coroutines.test.runTest import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule import net.mullvad.mullvadvpn.repository.ChangelogRepository -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class ChangelogViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() @MockK private lateinit var mockedChangelogRepository: ChangelogRepository private lateinit var viewModel: ChangelogViewModel - @Before + @BeforeEach fun setup() { MockKAnnotations.init(this) mockkStatic(EVENT_NOTIFIER_EXTENSION_CLASS) @@ -32,7 +32,7 @@ class ChangelogViewModelTest { Runs } - @After + @AfterEach fun teardown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt index 47364652ce..a1e3ce57e5 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt @@ -43,13 +43,13 @@ import net.mullvad.mullvadvpn.usecase.RelayListUseCase import net.mullvad.mullvadvpn.util.appVersionCallbackFlow import net.mullvad.talpid.tunnel.ErrorState import net.mullvad.talpid.util.EventNotifier -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class ConnectViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockServiceConnectionManager: ServiceConnectionManager = mockk() private lateinit var viewModel: ConnectViewModel @@ -102,7 +102,7 @@ class ConnectViewModelTest { private val outOfTimeUseCase: OutOfTimeUseCase = mockk() private val outOfTimeViewFlow = MutableStateFlow(false) - @Before + @BeforeEach fun setup() { mockkStatic(CACHE_EXTENSION_CLASS) mockkStatic(SERVICE_CONNECTION_MANAGER_EXTENSIONS) @@ -148,7 +148,7 @@ class ConnectViewModelTest { ) } - @After + @AfterEach fun teardown() { viewModel.viewModelScope.coroutineContext.cancel() unmockkAll() @@ -160,83 +160,79 @@ class ConnectViewModelTest { } @Test - fun testTunnelRealStateUpdate() = - runTest(testCoroutineRule.testDispatcher) { - val tunnelRealStateTestItem = TunnelState.Connected(mockk(relaxed = true), null) + fun testTunnelRealStateUpdate() = runTest { + val tunnelRealStateTestItem = TunnelState.Connected(mockk(relaxed = true), null) - viewModel.uiState.test { - assertEquals(ConnectUiState.INITIAL, awaitItem()) - serviceConnectionState.value = - ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) - eventNotifierTunnelRealState.notify(tunnelRealStateTestItem) - val result = awaitItem() - assertEquals(tunnelRealStateTestItem, result.tunnelRealState) - } + viewModel.uiState.test { + assertEquals(ConnectUiState.INITIAL, awaitItem()) + serviceConnectionState.value = + ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) + eventNotifierTunnelRealState.notify(tunnelRealStateTestItem) + val result = awaitItem() + assertEquals(tunnelRealStateTestItem, result.tunnelRealState) } + } @Test - fun testTunnelUiStateUpdate() = - runTest(testCoroutineRule.testDispatcher) { - val tunnelUiStateTestItem = TunnelState.Connected(mockk(), mockk()) + fun testTunnelUiStateUpdate() = runTest { + val tunnelUiStateTestItem = TunnelState.Connected(mockk(), mockk()) - viewModel.uiState.test { - assertEquals(ConnectUiState.INITIAL, awaitItem()) - serviceConnectionState.value = - ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) - eventNotifierTunnelUiState.notify(tunnelUiStateTestItem) - val result = awaitItem() - assertEquals(tunnelUiStateTestItem, result.tunnelUiState) - } + viewModel.uiState.test { + assertEquals(ConnectUiState.INITIAL, awaitItem()) + serviceConnectionState.value = + ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) + eventNotifierTunnelUiState.notify(tunnelUiStateTestItem) + val result = awaitItem() + assertEquals(tunnelUiStateTestItem, result.tunnelUiState) } + } @Test - fun testRelayItemUpdate() = - runTest(testCoroutineRule.testDispatcher) { - val relayTestItem = - RelayCountry(name = "Name", code = "Code", expanded = false, cities = emptyList()) - selectedRelayFlow.value = relayTestItem + fun testRelayItemUpdate() = runTest { + val relayTestItem = + RelayCountry(name = "Name", code = "Code", expanded = false, cities = emptyList()) + selectedRelayFlow.value = relayTestItem - viewModel.uiState.test { - assertEquals(ConnectUiState.INITIAL, awaitItem()) - serviceConnectionState.value = - ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) - val result = awaitItem() - assertEquals(relayTestItem, result.relayLocation) - } + viewModel.uiState.test { + assertEquals(ConnectUiState.INITIAL, awaitItem()) + serviceConnectionState.value = + ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) + val result = awaitItem() + assertEquals(relayTestItem, result.relayLocation) } + } @Test - fun testLocationUpdate() = - runTest(testCoroutineRule.testDispatcher) { - val locationTestItem = - GeoIpLocation( - ipv4 = mockk(relaxed = true), - ipv6 = mockk(relaxed = true), - country = "Sweden", - city = "Gothenburg", - hostname = "Host" - ) + fun testLocationUpdate() = runTest { + val locationTestItem = + GeoIpLocation( + ipv4 = mockk(relaxed = true), + ipv6 = mockk(relaxed = true), + country = "Sweden", + city = "Gothenburg", + hostname = "Host" + ) - // Act, Assert - viewModel.uiState.test { - assertEquals(ConnectUiState.INITIAL, awaitItem()) - eventNotifierTunnelRealState.notify(TunnelState.Disconnected(null)) + // Act, Assert + viewModel.uiState.test { + assertEquals(ConnectUiState.INITIAL, awaitItem()) + eventNotifierTunnelRealState.notify(TunnelState.Disconnected(null)) - serviceConnectionState.value = - ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) - // Start of with no location - assertNull(awaitItem().location) + serviceConnectionState.value = + ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) + // Start of with no location + assertNull(awaitItem().location) - // After updated we show latest - eventNotifierTunnelRealState.notify(TunnelState.Disconnected(locationTestItem)) - assertEquals(locationTestItem, awaitItem().location) - } + // After updated we show latest + eventNotifierTunnelRealState.notify(TunnelState.Disconnected(locationTestItem)) + assertEquals(locationTestItem, awaitItem().location) } + } @Test fun testLocationUpdateNullLocation() = // Arrange - runTest(testCoroutineRule.testDispatcher) { + runTest { val locationTestItem = null // Act, Assert @@ -251,99 +247,91 @@ class ConnectViewModelTest { } @Test - fun testOnDisconnectClick() = - runTest(testCoroutineRule.testDispatcher) { - val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true) - every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy - viewModel.onDisconnectClick() - verify { mockConnectionProxy.disconnect() } - } + fun testOnDisconnectClick() = runTest { + val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true) + every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy + viewModel.onDisconnectClick() + verify { mockConnectionProxy.disconnect() } + } @Test - fun testOnReconnectClick() = - runTest(testCoroutineRule.testDispatcher) { - val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true) - every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy - viewModel.onReconnectClick() - verify { mockConnectionProxy.reconnect() } - } + fun testOnReconnectClick() = runTest { + val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true) + every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy + viewModel.onReconnectClick() + verify { mockConnectionProxy.reconnect() } + } @Test - fun testOnConnectClick() = - runTest(testCoroutineRule.testDispatcher) { - val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true) - every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy - viewModel.onConnectClick() - verify { mockConnectionProxy.connect() } - } + fun testOnConnectClick() = runTest { + val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true) + every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy + viewModel.onConnectClick() + verify { mockConnectionProxy.connect() } + } @Test - fun testOnCancelClick() = - runTest(testCoroutineRule.testDispatcher) { - val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true) - every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy - viewModel.onCancelClick() - verify { mockConnectionProxy.disconnect() } - } + fun testOnCancelClick() = runTest { + val mockConnectionProxy: ConnectionProxy = mockk(relaxed = true) + every { mockServiceConnectionManager.connectionProxy() } returns mockConnectionProxy + viewModel.onCancelClick() + verify { mockConnectionProxy.disconnect() } + } @Test - fun testErrorNotificationState() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val mockErrorState: ErrorState = mockk() - val expectedConnectNotificationState = - InAppNotification.TunnelStateError(mockErrorState) - val tunnelUiState = TunnelState.Error(mockErrorState) - notifications.value = listOf(expectedConnectNotificationState) + fun testErrorNotificationState() = runTest { + // Arrange + val mockErrorState: ErrorState = mockk() + val expectedConnectNotificationState = InAppNotification.TunnelStateError(mockErrorState) + val tunnelUiState = TunnelState.Error(mockErrorState) + notifications.value = listOf(expectedConnectNotificationState) - // Act, Assert - viewModel.uiState.test { - assertEquals(ConnectUiState.INITIAL, awaitItem()) - serviceConnectionState.value = - ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) - eventNotifierTunnelUiState.notify(tunnelUiState) - val result = awaitItem() - assertEquals(expectedConnectNotificationState, result.inAppNotification) - } + // Act, Assert + viewModel.uiState.test { + assertEquals(ConnectUiState.INITIAL, awaitItem()) + serviceConnectionState.value = + ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) + eventNotifierTunnelUiState.notify(tunnelUiState) + val result = awaitItem() + assertEquals(expectedConnectNotificationState, result.inAppNotification) } + } @Test - fun testOnShowAccountClick() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val mockToken = "4444 5555 6666 7777" - val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true) - every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache - coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken + fun testOnShowAccountClick() = runTest { + // Arrange + val mockToken = "4444 5555 6666 7777" + val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true) + every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache + coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken - // Act, Assert - viewModel.uiSideEffect.test { - viewModel.onManageAccountClick() - val action = awaitItem() - assertIs<ConnectViewModel.UiSideEffect.OpenAccountManagementPageInBrowser>(action) - assertEquals(mockToken, action.token) - } + // Act, Assert + viewModel.uiSideEffect.test { + viewModel.onManageAccountClick() + val action = awaitItem() + assertIs<ConnectViewModel.UiSideEffect.OpenAccountManagementPageInBrowser>(action) + assertEquals(mockToken, action.token) } + } @Test - fun testOutOfTimeUiSideEffect() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val deferred = async { viewModel.uiSideEffect.first() } - - // Act - viewModel.uiState.test { - awaitItem() - serviceConnectionState.value = - ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) - outOfTimeViewFlow.value = true - awaitItem() - } + fun testOutOfTimeUiSideEffect() = runTest { + // Arrange + val deferred = async { viewModel.uiSideEffect.first() } - // Assert - assertIs<ConnectViewModel.UiSideEffect.OutOfTime>(deferred.await()) + // Act + viewModel.uiState.test { + awaitItem() + serviceConnectionState.value = + ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) + outOfTimeViewFlow.value = true + awaitItem() } + // Assert + assertIs<ConnectViewModel.UiSideEffect.OutOfTime>(deferred.await()) + } + companion object { private const val CACHE_EXTENSION_CLASS = "net.mullvad.mullvadvpn.util.CacheExtensionsKt" private const val SERVICE_CONNECTION_MANAGER_EXTENSIONS = diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt index 0fcf684afc..3f7966e8bd 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt @@ -11,7 +11,6 @@ import io.mockk.mockkStatic import io.mockk.unmockkAll import io.mockk.verify import io.mockk.verifyOrder -import junit.framework.Assert.assertEquals import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest @@ -25,13 +24,14 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState import net.mullvad.talpid.util.EventNotifier import net.mullvad.talpid.util.callbackFlowFromSubscription -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class DeviceRevokedViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() @MockK private lateinit var mockedAccountRepository: AccountRepository @@ -42,7 +42,7 @@ class DeviceRevokedViewModelTest { private lateinit var viewModel: DeviceRevokedViewModel - @Before + @BeforeEach fun setup() { MockKAnnotations.init(this) mockkStatic(EVENT_NOTIFIER_EXTENSION_CLASS) @@ -55,7 +55,7 @@ class DeviceRevokedViewModelTest { ) } - @After + @AfterEach fun teardown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/FilterViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/FilterViewModelTest.kt index 9f61ea4a91..210ed88666 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/FilterViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/FilterViewModelTest.kt @@ -20,13 +20,13 @@ import net.mullvad.mullvadvpn.model.Ownership import net.mullvad.mullvadvpn.model.Providers import net.mullvad.mullvadvpn.relaylist.Provider import net.mullvad.mullvadvpn.usecase.RelayListFilterUseCase -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class FilterViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockRelayListFilterUseCase: RelayListFilterUseCase = mockk(relaxed = true) private lateinit var viewModel: FilterViewModel private val selectedOwnership = @@ -54,7 +54,7 @@ class FilterViewModelTest { private val mockSelectedProviders: List<Provider> = listOf(Provider("31173", true), Provider("Blix", true), Provider("Creanova", true)) - @Before + @BeforeEach fun setup() { every { mockRelayListFilterUseCase.selectedOwnership() } returns selectedOwnership every { mockRelayListFilterUseCase.availableProviders() } returns @@ -64,7 +64,7 @@ class FilterViewModelTest { viewModel = FilterViewModel(mockRelayListFilterUseCase) } - @After + @AfterEach fun teardown() { viewModel.viewModelScope.coroutineContext.cancel() unmockkAll() diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt index c402a3103e..f677615c24 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt @@ -30,13 +30,13 @@ import net.mullvad.mullvadvpn.repository.DeviceRepository import net.mullvad.mullvadvpn.usecase.ConnectivityUseCase import net.mullvad.mullvadvpn.usecase.NewDeviceNotificationUseCase import org.joda.time.DateTime -import org.junit.Assert.assertEquals -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class LoginViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() @MockK private lateinit var connectivityUseCase: ConnectivityUseCase @MockK private lateinit var mockedAccountRepository: AccountRepository @@ -46,7 +46,7 @@ class LoginViewModelTest { private lateinit var loginViewModel: LoginViewModel private val accountHistoryTestEvents = MutableStateFlow<AccountHistory>(AccountHistory.Missing) - @Before + @BeforeEach fun setup() { Dispatchers.setMain(UnconfinedTestDispatcher()) diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt index 50a9d8fb98..0df34e0747 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt @@ -38,13 +38,13 @@ import net.mullvad.mullvadvpn.usecase.PaymentUseCase import net.mullvad.talpid.util.EventNotifier import org.joda.time.DateTime import org.joda.time.ReadableInstant -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class OutOfTimeViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val serviceConnectionStateFlow = MutableStateFlow<ServiceConnectionState>(ServiceConnectionState.Disconnected) @@ -70,7 +70,7 @@ class OutOfTimeViewModelTest { private lateinit var viewModel: OutOfTimeViewModel - @Before + @BeforeEach fun setUp() { mockkStatic(SERVICE_CONNECTION_MANAGER_EXTENSIONS) mockkStatic(PURCHASE_RESULT_EXTENSIONS_CLASS) @@ -103,75 +103,71 @@ class OutOfTimeViewModelTest { ) } - @After + @AfterEach fun tearDown() { viewModel.viewModelScope.coroutineContext.cancel() unmockkAll() } @Test - fun testSitePaymentClick() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val mockToken = "4444 5555 6666 7777" - val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true) - every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache - coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken + fun testSitePaymentClick() = runTest { + // Arrange + val mockToken = "4444 5555 6666 7777" + val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true) + every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache + coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken - // Act, Assert - viewModel.uiSideEffect.test { - viewModel.onSitePaymentClick() - val action = awaitItem() - assertIs<OutOfTimeViewModel.UiSideEffect.OpenAccountView>(action) - assertEquals(mockToken, action.token) - } + // Act, Assert + viewModel.uiSideEffect.test { + viewModel.onSitePaymentClick() + val action = awaitItem() + assertIs<OutOfTimeViewModel.UiSideEffect.OpenAccountView>(action) + assertEquals(mockToken, action.token) } + } @Test - fun testUpdateTunnelState() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val tunnelRealStateTestItem = TunnelState.Connected(mockk(), mockk()) + fun testUpdateTunnelState() = runTest { + // Arrange + val tunnelRealStateTestItem = TunnelState.Connected(mockk(), mockk()) - // Act, Assert - viewModel.uiState.test { - assertEquals(OutOfTimeUiState(deviceName = ""), awaitItem()) - eventNotifierTunnelRealState.notify(tunnelRealStateTestItem) - serviceConnectionStateFlow.value = - ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) - val result = awaitItem() - assertEquals(tunnelRealStateTestItem, result.tunnelState) - } + // Act, Assert + viewModel.uiState.test { + assertEquals(OutOfTimeUiState(deviceName = ""), awaitItem()) + eventNotifierTunnelRealState.notify(tunnelRealStateTestItem) + serviceConnectionStateFlow.value = + ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) + val result = awaitItem() + assertEquals(tunnelRealStateTestItem, result.tunnelState) } + } @Test - fun testOpenConnectScreen() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val mockExpiryDate: DateTime = mockk() - every { mockExpiryDate.isAfter(any<ReadableInstant>()) } returns true + fun testOpenConnectScreen() = runTest { + // Arrange + val mockExpiryDate: DateTime = mockk() + every { mockExpiryDate.isAfter(any<ReadableInstant>()) } returns true - // Act, Assert - viewModel.uiSideEffect.test { - outOfTimeFlow.value = false - val action = awaitItem() - assertIs<OutOfTimeViewModel.UiSideEffect.OpenConnectScreen>(action) - } + // Act, Assert + viewModel.uiSideEffect.test { + outOfTimeFlow.value = false + val action = awaitItem() + assertIs<OutOfTimeViewModel.UiSideEffect.OpenConnectScreen>(action) } + } @Test - fun testOnDisconnectClick() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val mockProxy: ConnectionProxy = mockk(relaxed = true) - every { mockServiceConnectionManager.connectionProxy() } returns mockProxy + fun testOnDisconnectClick() = runTest { + // Arrange + val mockProxy: ConnectionProxy = mockk(relaxed = true) + every { mockServiceConnectionManager.connectionProxy() } returns mockProxy - // Act - viewModel.onDisconnectClick() + // Act + viewModel.onDisconnectClick() - // Assert - verify { mockProxy.disconnect() } - } + // Assert + verify { mockProxy.disconnect() } + } @Test fun testBillingProductsUnavailableState() = runTest { diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/PaymentViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/PaymentViewModelTest.kt index 665e23c3d4..1e2fba3c96 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/PaymentViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/PaymentViewModelTest.kt @@ -12,13 +12,13 @@ import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule import net.mullvad.mullvadvpn.lib.payment.model.PurchaseResult import net.mullvad.mullvadvpn.usecase.PaymentUseCase import net.mullvad.mullvadvpn.util.toPaymentDialogData -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class PaymentViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockPaymentUseCase: PaymentUseCase = mockk(relaxed = true) @@ -26,14 +26,14 @@ class PaymentViewModelTest { private lateinit var viewModel: PaymentViewModel - @Before + @BeforeEach fun setUp() { coEvery { mockPaymentUseCase.purchaseResult } returns purchaseResult viewModel = PaymentViewModel(paymentUseCase = mockPaymentUseCase) } - @After + @AfterEach fun tearDown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ReportProblemViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ReportProblemViewModelTest.kt index 5726c6249c..6ea1a85ed2 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ReportProblemViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ReportProblemViewModelTest.kt @@ -15,13 +15,13 @@ import net.mullvad.mullvadvpn.dataproxy.SendProblemReportResult import net.mullvad.mullvadvpn.dataproxy.UserReport import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule import net.mullvad.mullvadvpn.repository.ProblemReportRepository -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class ReportProblemViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() @MockK private lateinit var mockMullvadProblemReport: MullvadProblemReport @@ -31,7 +31,7 @@ class ReportProblemViewModelTest { private lateinit var viewModel: ReportProblemViewModel - @Before + @BeforeEach fun setUp() { MockKAnnotations.init(this) coEvery { mockMullvadProblemReport.collectLogs() } returns true @@ -39,7 +39,7 @@ class ReportProblemViewModelTest { viewModel = ReportProblemViewModel(mockMullvadProblemReport, mockProblemReportRepository) } - @After + @AfterEach fun tearDown() { viewModel.viewModelScope.coroutineContext.cancel() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt index 5ad1af1182..46ea0bf3fb 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt @@ -29,13 +29,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.ui.serviceconnection.connectionProxy import net.mullvad.mullvadvpn.usecase.RelayListFilterUseCase import net.mullvad.mullvadvpn.usecase.RelayListUseCase -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class SelectLocationViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockRelayListFilterUseCase: RelayListFilterUseCase = mockk(relaxed = true) private val mockServiceConnectionManager: ServiceConnectionManager = mockk() @@ -46,7 +46,7 @@ class SelectLocationViewModelTest { private val selectedProvider = MutableStateFlow<Constraint<Providers>>(Constraint.Any()) private val allProvider = MutableStateFlow<List<Provider>>(emptyList()) - @Before + @BeforeEach fun setup() { every { mockRelayListFilterUseCase.selectedOwnership() } returns selectedOwnership @@ -64,7 +64,7 @@ class SelectLocationViewModelTest { ) } - @After + @AfterEach fun teardown() { viewModel.viewModelScope.coroutineContext.cancel() unmockkAll() diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt index ff6804c953..b52ab53ef6 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt @@ -19,13 +19,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState import net.mullvad.mullvadvpn.util.appVersionCallbackFlow -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class SettingsViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockDeviceRepository: DeviceRepository = mockk() private val mockServiceConnectionManager: ServiceConnectionManager = mockk() @@ -46,7 +46,7 @@ class SettingsViewModelTest { private lateinit var viewModel: SettingsViewModel - @Before + @BeforeEach fun setUp() { mockkStatic(CACHE_EXTENSION_CLASS) val deviceState = MutableStateFlow<DeviceState>(DeviceState.LoggedOut) @@ -68,7 +68,7 @@ class SettingsViewModelTest { ) } - @After + @AfterEach fun tearDown() { viewModel.viewModelScope.coroutineContext.cancel() unmockkAll() diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt index 5409b7f736..7b2b4cacd5 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SplitTunnelingViewModelTest.kt @@ -15,6 +15,7 @@ import java.util.concurrent.TimeUnit import kotlin.test.assertEquals import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import net.mullvad.mullvadvpn.applist.AppData import net.mullvad.mullvadvpn.applist.ApplicationsProvider @@ -24,174 +25,169 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionContainer import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState import net.mullvad.mullvadvpn.ui.serviceconnection.SplitTunneling -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.rules.Timeout +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.Timeout +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) +@Timeout(3000L, unit = TimeUnit.MILLISECONDS) class SplitTunnelingViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() - @get:Rule val timeout = Timeout(3000L, TimeUnit.MILLISECONDS) private val mockedApplicationsProvider = mockk<ApplicationsProvider>() private val mockedSplitTunneling = mockk<SplitTunneling>() private val mockedServiceConnectionManager = mockk<ServiceConnectionManager>() private val mockedServiceConnectionContainer = mockk<ServiceConnectionContainer>() private lateinit var testSubject: SplitTunnelingViewModel - @Before + @BeforeEach fun setup() { every { mockedSplitTunneling.enabled } returns true } - @After + @AfterEach fun tearDown() { testSubject.viewModelScope.coroutineContext.cancel() unmockkAll() } @Test - fun test_has_progress_on_start() = - runTest(testCoroutineRule.testDispatcher) { - initTestSubject(emptyList()) - val actualState: SplitTunnelingUiState = testSubject.uiState.value + fun test_has_progress_on_start() = runTest { + initTestSubject(emptyList()) + val actualState: SplitTunnelingUiState = testSubject.uiState.value - val initialExpectedState = SplitTunnelingUiState.Loading + val initialExpectedState = SplitTunnelingUiState.Loading - assertEquals(initialExpectedState, actualState) + assertEquals(initialExpectedState, actualState) - verify(exactly = 1) { mockedApplicationsProvider.getAppsList() } - } + verify(exactly = 1) { mockedApplicationsProvider.getAppsList() } + } @Test - fun test_empty_app_list() = - runTest(testCoroutineRule.testDispatcher) { - every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers - { - lambda<(Set<String>) -> Unit>().invoke(emptySet()) - } - initTestSubject(emptyList()) - val expectedState = - SplitTunnelingUiState.ShowAppList( - excludedApps = emptyList(), - includedApps = emptyList(), - showSystemApps = false - ) - testSubject.uiState.test { assertEquals(expectedState, awaitItem()) } - } + fun test_empty_app_list() = runTest { + every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers + { + lambda<(Set<String>) -> Unit>().invoke(emptySet()) + } + initTestSubject(emptyList()) + val expectedState = + SplitTunnelingUiState.ShowAppList( + excludedApps = emptyList(), + includedApps = emptyList(), + showSystemApps = false + ) + testSubject.uiState.test { assertEquals(expectedState, awaitItem()) } + } @Test - fun test_apps_list_delivered() = - runTest(testCoroutineRule.testDispatcher) { - val appExcluded = AppData("test.excluded", 0, "testName1") - val appNotExcluded = AppData("test.not.excluded", 0, "testName2") - every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers - { - lambda<(Set<String>) -> Unit>().invoke(setOf(appExcluded.packageName)) - } + fun test_apps_list_delivered() = runTest { + val appExcluded = AppData("test.excluded", 0, "testName1") + val appNotExcluded = AppData("test.not.excluded", 0, "testName2") + every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers + { + lambda<(Set<String>) -> Unit>().invoke(setOf(appExcluded.packageName)) + } - initTestSubject(listOf(appExcluded, appNotExcluded)) + initTestSubject(listOf(appExcluded, appNotExcluded)) - val expectedState = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(appExcluded), - includedApps = listOf(appNotExcluded), - showSystemApps = false - ) + val expectedState = + SplitTunnelingUiState.ShowAppList( + excludedApps = listOf(appExcluded), + includedApps = listOf(appNotExcluded), + showSystemApps = false + ) - testSubject.uiState.test { - val actualState = awaitItem() - assertEquals(expectedState, actualState) - verifyAll { - mockedSplitTunneling.enabled - mockedSplitTunneling.excludedAppsChange = any() - } + testSubject.uiState.test { + val actualState = awaitItem() + assertEquals(expectedState, actualState) + verifyAll { + mockedSplitTunneling.enabled + mockedSplitTunneling.excludedAppsChange = any() } } + } @Test - fun test_include_app() = - runTest(testCoroutineRule.testDispatcher) { - var excludedAppsCallback = slot<(Set<String>) -> Unit>() - val app = AppData("test", 0, "testName") - every { mockedSplitTunneling.includeApp(app.packageName) } just runs - every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers - { - excludedAppsCallback = lambda() - excludedAppsCallback.invoke(setOf(app.packageName)) - } + fun test_include_app() = runTest { + var excludedAppsCallback = slot<(Set<String>) -> Unit>() + val app = AppData("test", 0, "testName") + every { mockedSplitTunneling.includeApp(app.packageName) } just runs + every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers + { + excludedAppsCallback = lambda() + excludedAppsCallback.invoke(setOf(app.packageName)) + } - initTestSubject(listOf(app)) + initTestSubject(listOf(app)) - val expectedStateBeforeAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(app), - includedApps = emptyList(), - showSystemApps = false - ) - val expectedStateAfterAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = emptyList(), - includedApps = listOf(app), - showSystemApps = false - ) + val expectedStateBeforeAction = + SplitTunnelingUiState.ShowAppList( + excludedApps = listOf(app), + includedApps = emptyList(), + showSystemApps = false + ) + val expectedStateAfterAction = + SplitTunnelingUiState.ShowAppList( + excludedApps = emptyList(), + includedApps = listOf(app), + showSystemApps = false + ) - testSubject.uiState.test { - assertEquals(expectedStateBeforeAction, awaitItem()) - testSubject.onIncludeAppClick(app.packageName) - excludedAppsCallback.invoke(emptySet()) - assertEquals(expectedStateAfterAction, awaitItem()) + testSubject.uiState.test { + assertEquals(expectedStateBeforeAction, awaitItem()) + testSubject.onIncludeAppClick(app.packageName) + excludedAppsCallback.invoke(emptySet()) + assertEquals(expectedStateAfterAction, awaitItem()) - verifyAll { - mockedSplitTunneling.enabled - mockedSplitTunneling.excludedAppsChange = any() - mockedSplitTunneling.includeApp(app.packageName) - } + verifyAll { + mockedSplitTunneling.enabled + mockedSplitTunneling.excludedAppsChange = any() + mockedSplitTunneling.includeApp(app.packageName) } } + } @Test - fun test_add_app_to_excluded() = - runTest(testCoroutineRule.testDispatcher) { - var excludedAppsCallback = slot<(Set<String>) -> Unit>() - val app = AppData("test", 0, "testName") - every { mockedSplitTunneling.excludeApp(app.packageName) } just runs - every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers - { - excludedAppsCallback = lambda() - excludedAppsCallback.invoke(emptySet()) - } + fun test_add_app_to_excluded() = runTest { + var excludedAppsCallback = slot<(Set<String>) -> Unit>() + val app = AppData("test", 0, "testName") + every { mockedSplitTunneling.excludeApp(app.packageName) } just runs + every { mockedSplitTunneling.excludedAppsChange = captureLambda() } answers + { + excludedAppsCallback = lambda() + excludedAppsCallback.invoke(emptySet()) + } - initTestSubject(listOf(app)) + initTestSubject(listOf(app)) - val expectedStateBeforeAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = emptyList(), - includedApps = listOf(app), - showSystemApps = false - ) + val expectedStateBeforeAction = + SplitTunnelingUiState.ShowAppList( + excludedApps = emptyList(), + includedApps = listOf(app), + showSystemApps = false + ) - val expectedStateAfterAction = - SplitTunnelingUiState.ShowAppList( - excludedApps = listOf(app), - includedApps = emptyList(), - showSystemApps = false - ) + val expectedStateAfterAction = + SplitTunnelingUiState.ShowAppList( + excludedApps = listOf(app), + includedApps = emptyList(), + showSystemApps = false + ) - testSubject.uiState.test { - assertEquals(expectedStateBeforeAction, awaitItem()) - testSubject.onExcludeAppClick(app.packageName) - excludedAppsCallback.invoke(setOf(app.packageName)) - assertEquals(expectedStateAfterAction, awaitItem()) + testSubject.uiState.test { + assertEquals(expectedStateBeforeAction, awaitItem()) + testSubject.onExcludeAppClick(app.packageName) + excludedAppsCallback.invoke(setOf(app.packageName)) + assertEquals(expectedStateAfterAction, awaitItem()) - verifyAll { - mockedSplitTunneling.enabled - mockedSplitTunneling.excludedAppsChange = any() - mockedSplitTunneling.excludeApp(app.packageName) - } + verifyAll { + mockedSplitTunneling.enabled + mockedSplitTunneling.excludedAppsChange = any() + mockedSplitTunneling.excludeApp(app.packageName) } } + } private fun initTestSubject(appList: List<AppData>) { every { mockedApplicationsProvider.getAppsList() } returns appList @@ -204,7 +200,7 @@ class SplitTunnelingViewModelTest { SplitTunnelingViewModel( mockedApplicationsProvider, mockedServiceConnectionManager, - testCoroutineRule.testDispatcher + UnconfinedTestDispatcher() ) } } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModelTest.kt index bfa068a381..7c54cd2c5e 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VoucherDialogViewModelTest.kt @@ -22,13 +22,13 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState import net.mullvad.mullvadvpn.ui.serviceconnection.VoucherRedeemer import net.mullvad.mullvadvpn.ui.serviceconnection.voucherRedeemer -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class VoucherDialogViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockServiceConnectionManager: ServiceConnectionManager = mockk() private val mockServiceConnectionContainer: ServiceConnectionContainer = mockk() @@ -41,7 +41,7 @@ class VoucherDialogViewModelTest { private lateinit var viewModel: VoucherDialogViewModel - @Before + @BeforeEach fun setUp() { every { mockServiceConnectionManager.connectionState } returns serviceConnectionState @@ -52,7 +52,7 @@ class VoucherDialogViewModelTest { ) } - @After + @AfterEach fun tearDown() { unmockkAll() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt index 0ac13777cd..51bbe3057c 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt @@ -27,13 +27,13 @@ import net.mullvad.mullvadvpn.model.WireguardTunnelOptions import net.mullvad.mullvadvpn.repository.SettingsRepository import net.mullvad.mullvadvpn.usecase.PortRangeUseCase import net.mullvad.mullvadvpn.usecase.RelayListUseCase -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class VpnSettingsViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val mockSettingsRepository: SettingsRepository = mockk() private val mockResources: Resources = mockk() @@ -45,7 +45,7 @@ class VpnSettingsViewModelTest { private lateinit var viewModel: VpnSettingsViewModel - @Before + @BeforeEach fun setUp() { every { mockSettingsRepository.settingsUpdates } returns mockSettingsUpdate every { mockPortRangeUseCase.portRanges() } returns portRangeFlow @@ -60,7 +60,7 @@ class VpnSettingsViewModelTest { ) } - @After + @AfterEach fun tearDown() { viewModel.viewModelScope.coroutineContext.cancel() unmockkAll() diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt index 29b0dfde75..d0461a4ee5 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt @@ -37,13 +37,13 @@ import net.mullvad.mullvadvpn.usecase.PaymentUseCase import net.mullvad.talpid.util.EventNotifier import org.joda.time.DateTime import org.joda.time.ReadableInstant -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +@ExtendWith(TestCoroutineRule::class) class WelcomeViewModelTest { - @get:Rule val testCoroutineRule = TestCoroutineRule() private val serviceConnectionStateFlow = MutableStateFlow<ServiceConnectionState>(ServiceConnectionState.Disconnected) @@ -68,7 +68,7 @@ class WelcomeViewModelTest { private lateinit var viewModel: WelcomeViewModel - @Before + @BeforeEach fun setUp() { mockkStatic(SERVICE_CONNECTION_MANAGER_EXTENSIONS) mockkStatic(PURCHASE_RESULT_EXTENSIONS_CLASS) @@ -101,46 +101,44 @@ class WelcomeViewModelTest { ) } - @After + @AfterEach fun tearDown() { viewModel.viewModelScope.coroutineContext.cancel() unmockkAll() } @Test - fun testSitePaymentClick() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val mockToken = "4444 5555 6666 7777" - val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true) - every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache - coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken + fun testSitePaymentClick() = runTest { + // Arrange + val mockToken = "4444 5555 6666 7777" + val mockAuthTokenCache: AuthTokenCache = mockk(relaxed = true) + every { mockServiceConnectionManager.authTokenCache() } returns mockAuthTokenCache + coEvery { mockAuthTokenCache.fetchAuthToken() } returns mockToken - // Act, Assert - viewModel.uiSideEffect.test { - viewModel.onSitePaymentClick() - val action = awaitItem() - assertIs<WelcomeViewModel.UiSideEffect.OpenAccountView>(action) - assertEquals(mockToken, action.token) - } + // Act, Assert + viewModel.uiSideEffect.test { + viewModel.onSitePaymentClick() + val action = awaitItem() + assertIs<WelcomeViewModel.UiSideEffect.OpenAccountView>(action) + assertEquals(mockToken, action.token) } + } @Test - fun testUpdateTunnelState() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val tunnelUiStateTestItem = TunnelState.Connected(mockk(), mockk()) + fun testUpdateTunnelState() = runTest { + // Arrange + val tunnelUiStateTestItem = TunnelState.Connected(mockk(), mockk()) - // Act, Assert - viewModel.uiState.test { - assertEquals(WelcomeUiState(), awaitItem()) - eventNotifierTunnelUiState.notify(tunnelUiStateTestItem) - serviceConnectionStateFlow.value = - ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) - val result = awaitItem() - assertEquals(tunnelUiStateTestItem, result.tunnelState) - } + // Act, Assert + viewModel.uiState.test { + assertEquals(WelcomeUiState(), awaitItem()) + eventNotifierTunnelUiState.notify(tunnelUiStateTestItem) + serviceConnectionStateFlow.value = + ServiceConnectionState.ConnectedReady(mockServiceConnectionContainer) + val result = awaitItem() + assertEquals(tunnelUiStateTestItem, result.tunnelState) } + } @Test fun testUpdateAccountNumber() = runTest { @@ -165,19 +163,18 @@ class WelcomeViewModelTest { } @Test - fun testOpenConnectScreen() = - runTest(testCoroutineRule.testDispatcher) { - // Arrange - val mockExpiryDate: DateTime = mockk() - every { mockExpiryDate.isAfter(any<ReadableInstant>()) } returns true + fun testOpenConnectScreen() = runTest { + // Arrange + val mockExpiryDate: DateTime = mockk() + every { mockExpiryDate.isAfter(any<ReadableInstant>()) } returns true - // Act, Assert - viewModel.uiSideEffect.test { - outOfTimeFlow.value = false - val action = awaitItem() - assertIs<WelcomeViewModel.UiSideEffect.OpenConnectScreen>(action) - } + // Act, Assert + viewModel.uiSideEffect.test { + outOfTimeFlow.value = false + val action = awaitItem() + assertIs<WelcomeViewModel.UiSideEffect.OpenConnectScreen>(action) } + } @Test fun testBillingProductsUnavailableState() = runTest { diff --git a/android/buildSrc/src/main/kotlin/Dependencies.kt b/android/buildSrc/src/main/kotlin/Dependencies.kt index 8e38491f41..c68e6b417c 100644 --- a/android/buildSrc/src/main/kotlin/Dependencies.kt +++ b/android/buildSrc/src/main/kotlin/Dependencies.kt @@ -2,7 +2,15 @@ object Dependencies { const val androidVolley = "com.android.volley:volley:${Versions.Android.volley}" const val commonsValidator = "commons-validator:commons-validator:${Versions.commonsValidator}" const val jodaTime = "joda-time:joda-time:${Versions.jodaTime}" - const val junit = "junit:junit:${Versions.junit}" + const val junitApi = "org.junit.jupiter:junit-jupiter-api:${Versions.junit}" + const val junitEngine = "org.junit.jupiter:junit-jupiter-engine:${Versions.junit}" + const val junitParams = "org.junit.jupiter:junit-jupiter-params:${Versions.junit}" + const val junitAndroidTestExtensions = + "de.mannodermaus.junit5:android-test-core:${Versions.Android.junit}" + const val junitAndroidTestCore = + "de.mannodermaus.junit5:android-test-extensions:${Versions.Android.junit}" + const val junitAndroidTestRunner = + "de.mannodermaus.junit5:android-test-runner:${Versions.Android.junit}" const val konsist = "com.lemonappdev:konsist:${Versions.konsist}" const val leakCanary = "com.squareup.leakcanary:leakcanary-android:${Versions.leakCanary}" const val mockkWebserver = "com.squareup.okhttp3:mockwebserver:${Versions.mockWebserver}" @@ -22,14 +30,10 @@ object Dependencies { "androidx.lifecycle:lifecycle-viewmodel-ktx:${Versions.AndroidX.lifecycle}" const val espressoCore = "androidx.test.espresso:espresso-core:${Versions.AndroidX.espresso}" - const val testCore = - "androidx.test:core:${Versions.AndroidX.test}" - const val testMonitor = - "androidx.test:monitor:${Versions.AndroidX.testMonitor}" - const val testRunner = - "androidx.test:runner:${Versions.AndroidX.testRunner}" - const val testRules = - "androidx.test:rules:${Versions.AndroidX.test}" + const val testCore = "androidx.test:core:${Versions.AndroidX.test}" + const val testMonitor = "androidx.test:monitor:${Versions.AndroidX.testMonitor}" + const val testRunner = "androidx.test:runner:${Versions.AndroidX.testRunner}" + const val testRules = "androidx.test:rules:${Versions.AndroidX.test}" const val testUiAutomator = "androidx.test.uiautomator:uiautomator:${Versions.AndroidX.uiautomator}" const val testOrchestrator = @@ -37,25 +41,27 @@ object Dependencies { } object Compose { - const val destinations = "io.github.raamcosta.compose-destinations:core:${Versions.Compose.destinations}" - const val destinationsKsp = "io.github.raamcosta.compose-destinations:ksp:${Versions.Compose.destinations}" const val constrainLayout = "androidx.constraintlayout:constraintlayout-compose:${Versions.Compose.constrainLayout}" + const val destinations = + "io.github.raamcosta.compose-destinations:core:${Versions.Compose.destinations}" + const val destinationsKsp = + "io.github.raamcosta.compose-destinations:ksp:${Versions.Compose.destinations}" const val foundation = "androidx.compose.foundation:foundation:${Versions.Compose.foundation}" - const val junit = "androidx.compose.ui:ui-test-junit4:${Versions.Compose.base}" + const val junit5 = "de.mannodermaus.junit5:android-test-compose:${Versions.Android.junit}" const val material3 = "androidx.compose.material3:material3:${Versions.Compose.material3}" const val testManifest = "androidx.compose.ui:ui-test-manifest:${Versions.Compose.base}" + const val ui = "androidx.compose.ui:ui:${Versions.Compose.base}" const val uiController = "com.google.accompanist:accompanist-systemuicontroller:${Versions.Compose.uiController}" - const val ui = "androidx.compose.ui:ui:${Versions.Compose.base}" - const val uiUtil = "androidx.compose.ui:ui-util:${Versions.Compose.base}" + const val uiTestManifest = "androidx.compose.ui:ui-test-manifest:${Versions.Compose.base}" const val uiTooling = "androidx.compose.ui:ui-tooling:${Versions.Compose.base}" - const val uiToolingPreview = - "androidx.compose.ui:ui-tooling-preview:${Versions.Compose.base}" const val uiToolingAndroidPreview = "androidx.compose.ui:ui-tooling-preview-android:${Versions.Compose.base}" - + const val uiToolingPreview = + "androidx.compose.ui:ui-tooling-preview:${Versions.Compose.base}" + const val uiUtil = "androidx.compose.ui:ui-util:${Versions.Compose.base}" } object Koin { @@ -111,17 +117,18 @@ object Dependencies { const val androidApplicationId = "com.android.application" const val androidLibraryId = "com.android.library" const val androidTestId = "com.android.test" - const val playPublisher = - "com.github.triplet.gradle:play-publisher:${Versions.Plugin.playPublisher}" - const val playPublisherId = "com.github.triplet.play" - const val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}" - const val kotlinAndroidId = "kotlin-android" - const val kotlinParcelizeId = "kotlin-parcelize" const val dependencyCheck = "org.owasp:dependency-check-gradle:${Versions.Plugin.dependencyCheck}" const val dependencyCheckId = "org.owasp.dependencycheck" const val gradleVersionsId = "com.github.ben-manes.versions" - const val ktfmtId = "com.ncorti.ktfmt.gradle" + const val junit5 = "de.mannodermaus.android-junit5" + const val kotlin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}" + const val kotlinAndroidId = "kotlin-android" + const val kotlinParcelizeId = "kotlin-parcelize" const val ksp = "com.google.devtools.ksp" + const val ktfmtId = "com.ncorti.ktfmt.gradle" + const val playPublisher = + "com.github.triplet.gradle:play-publisher:${Versions.Plugin.playPublisher}" + const val playPublisherId = "com.github.triplet.play" } } diff --git a/android/buildSrc/src/main/kotlin/Versions.kt b/android/buildSrc/src/main/kotlin/Versions.kt index fede1556f7..dc5c5d923b 100644 --- a/android/buildSrc/src/main/kotlin/Versions.kt +++ b/android/buildSrc/src/main/kotlin/Versions.kt @@ -1,7 +1,7 @@ object Versions { const val commonsValidator = "1.7" const val jodaTime = "2.12.5" - const val junit = "4.13.2" + const val junit = "5.10.0" const val jvmTarget = "17" const val konsist = "0.13.0" const val kotlin = "1.9.20" @@ -15,6 +15,7 @@ object Versions { object Android { const val compileSdkVersion = 34 + const val junit = "1.4.0" const val minSdkVersion = 26 const val targetSdkVersion = 34 const val volley = "1.2.1" @@ -52,6 +53,7 @@ object Versions { const val playPublisher = "3.8.4" const val dependencyCheck = "8.3.1" const val gradleVersions = "0.47.0" + const val junit5 = "1.10.0.0" const val ktfmt = "0.13.0" // Ksp version is linked with kotlin version, find matching release here: // https://github.com/google/ksp/releases diff --git a/android/lib/common-test/build.gradle.kts b/android/lib/common-test/build.gradle.kts index 3d0ef6c028..6e3fc7c02f 100644 --- a/android/lib/common-test/build.gradle.kts +++ b/android/lib/common-test/build.gradle.kts @@ -21,10 +21,20 @@ android { abortOnError = true warningsAsErrors = true } + + packaging { + resources { + pickFirsts += setOf( + // Fixes packaging error caused by: jetified-junit-* + "META-INF/LICENSE.md", + "META-INF/LICENSE-notice.md" + ) + } + } } dependencies { implementation(Dependencies.Kotlin.test) implementation(Dependencies.KotlinX.coroutinesTest) - implementation(Dependencies.junit) + implementation(Dependencies.junitApi) } diff --git a/android/lib/common-test/src/main/java/net/mullvad/mullvadvpn/lib/common/test/TestCoroutineRule.kt b/android/lib/common-test/src/main/java/net/mullvad/mullvadvpn/lib/common/test/TestCoroutineRule.kt index d04983be26..34d6739119 100644 --- a/android/lib/common-test/src/main/java/net/mullvad/mullvadvpn/lib/common/test/TestCoroutineRule.kt +++ b/android/lib/common-test/src/main/java/net/mullvad/mullvadvpn/lib/common/test/TestCoroutineRule.kt @@ -6,22 +6,20 @@ import kotlinx.coroutines.test.TestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.setMain -import org.junit.rules.TestWatcher -import org.junit.runner.Description +import org.junit.jupiter.api.extension.AfterEachCallback +import org.junit.jupiter.api.extension.BeforeEachCallback +import org.junit.jupiter.api.extension.ExtensionContext @OptIn(ExperimentalCoroutinesApi::class) class TestCoroutineRule(val testDispatcher: TestDispatcher = UnconfinedTestDispatcher()) : - TestWatcher() { + BeforeEachCallback, AfterEachCallback { - override fun starting(description: Description) { - super.starting(description) + override fun beforeEach(var1: ExtensionContext?) { Dispatchers.setMain(testDispatcher) } - override fun finished(description: Description) { - super.finished(description) + override fun afterEach(var1: ExtensionContext?) { Dispatchers.resetMain() - // Replacement for cleanupTestCoroutines() testDispatcher.scheduler.runCurrent() } } |
