diff --git a/build.gradle.kts b/build.gradle.kts index 513483e1..47ba2ab6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -219,10 +219,7 @@ dependencies { // Testing testImplementation(libs.junit) - testImplementation(libs.powermock.core) - testImplementation(libs.powermock.module.junit4) - testImplementation(libs.powermock.api.mockito2) - testImplementation(libs.mockito.core) // powermock isn't compatible with mockito 4 + testImplementation(libs.mockito.core) testImplementation(libs.jsonassert) // For device controls diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ad5db261..1faa8a25 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,8 +28,7 @@ material = "1.12.0" material3 = "1.2.1" media = "1.7.0" minaCore = "2.0.19" -mockitoCore = "3.12.4" -powermockModuleJunit4 = "2.0.9" +mockitoCore = "5.12.0" preferenceKtx = "1.2.1" reactiveStreams = "1.0.4" recyclerview = "1.3.2" @@ -78,9 +77,6 @@ material = { module = "com.google.android.material:material", version.ref = "mat apache-mina-core = { module = "org.apache.mina:mina-core", version.ref = "minaCore" } apache-sshd-core = { module = "org.apache.sshd:sshd-core", version.ref = "sshdCore" } mockito-core = { module = "org.mockito:mockito-core", version.ref = "mockitoCore" } -powermock-api-mockito2 = { module = "org.powermock:powermock-api-mockito2", version.ref = "powermockModuleJunit4" } -powermock-core = { module = "org.powermock:powermock-core", version.ref = "powermockModuleJunit4" } -powermock-module-junit4 = { module = "org.powermock:powermock-module-junit4", version.ref = "powermockModuleJunit4" } reactive-streams = { module = "org.reactivestreams:reactive-streams", version.ref = "reactiveStreams" } rxjava = { module = "io.reactivex.rxjava2:rxjava", version.ref = "rxjava" } univocity-parsers = { module = "com.univocity:univocity-parsers", version.ref = "univocityParsers" } diff --git a/src/org/kde/kdeconnect/PairingHandler.kt b/src/org/kde/kdeconnect/PairingHandler.kt index bad7a070..6373e3bf 100644 --- a/src/org/kde/kdeconnect/PairingHandler.kt +++ b/src/org/kde/kdeconnect/PairingHandler.kt @@ -6,6 +6,7 @@ package org.kde.kdeconnect import android.util.Log +import androidx.annotation.VisibleForTesting import kotlinx.coroutines.* import org.kde.kdeconnect_tp.R import kotlin.time.Duration.Companion.seconds @@ -155,7 +156,8 @@ class PairingHandler(private val device: Device, private val callback: PairingCa callback.pairingFailed(device.context.getString(R.string.error_canceled_by_user)) } - private fun pairingDone() { + @VisibleForTesting + fun pairingDone() { Log.i("PairingHandler", "Pairing done") state = PairState.Paired kotlin.runCatching { diff --git a/tests/android/util/Log.java b/tests/android/util/Log.java new file mode 100644 index 00000000..351cafec --- /dev/null +++ b/tests/android/util/Log.java @@ -0,0 +1,29 @@ +package android.util; + +// Based on https://stackoverflow.com/questions/36787449/how-to-mock-method-e-in-log +public class Log { + public static int d(String tag, String msg) { + System.out.println("DEBUG: " + tag + ": " + msg); + return 0; + } + + public static int i(String tag, String msg) { + System.out.println("INFO: " + tag + ": " + msg); + return 0; + } + + public static int w(String tag, String msg) { + System.out.println("WARN: " + tag + ": " + msg); + return 0; + } + + public static int e(String tag, String msg) { + System.out.println("ERROR: " + tag + ": " + msg); + return 0; + } + + public static int e(String tag, String msg, Throwable e) { + System.out.println("ERROR: " + tag + ": " + msg + ": " + e); + return 0; + } +} diff --git a/tests/org/kde/kdeconnect/DeviceTest.java b/tests/org/kde/kdeconnect/DeviceTest.java index d727ab7d..3fa2f12d 100644 --- a/tests/org/kde/kdeconnect/DeviceTest.java +++ b/tests/org/kde/kdeconnect/DeviceTest.java @@ -24,32 +24,37 @@ import android.util.Log; import androidx.core.content.ContextCompat; +import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; import org.kde.kdeconnect.Backends.LanBackend.LanLink; import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider; import org.kde.kdeconnect.Helpers.DeviceHelper; import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper; import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper; +import org.mockito.MockedStatic; import org.mockito.Mockito; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.util.Arrays; import java.util.HashSet; -@RunWith(PowerMockRunner.class) -@PrepareForTest({Base64.class, Log.class, PreferenceManager.class, ContextCompat.class}) public class DeviceTest { private Context context; + MockedStatic mockBase64; + MockedStatic preferenceManager; + MockedStatic contextCompat; + + @After + public void tearDown() { + mockBase64.close(); + preferenceManager.close(); + contextCompat.close(); + } + // Creating a paired device before each test case @Before public void setUp() { @@ -76,11 +81,11 @@ public class DeviceTest { this.context = Mockito.mock(Context.class); - PowerMockito.mockStatic(Base64.class); - PowerMockito.when(Base64.encodeToString(any(), anyInt())).thenAnswer(invocation -> java.util.Base64.getMimeEncoder().encodeToString((byte[]) invocation.getArguments()[0])); - PowerMockito.when(Base64.decode(anyString(), anyInt())).thenAnswer(invocation -> java.util.Base64.getMimeDecoder().decode((String) invocation.getArguments()[0])); + mockBase64 = Mockito.mockStatic(Base64.class); + mockBase64.when(() -> Base64.encodeToString(any(byte[].class), anyInt())).thenAnswer(invocation -> java.util.Base64.getMimeEncoder().encodeToString((byte[]) invocation.getArguments()[0])); + mockBase64.when(() -> Base64.decode(anyString(), anyInt())).thenAnswer(invocation -> java.util.Base64.getMimeDecoder().decode((String) invocation.getArguments()[0])); - PowerMockito.mockStatic(Log.class); + Mockito.mockStatic(Log.class).close(); //Store device information needed to create a Device object in a future MockSharedPreference deviceSettings = new MockSharedPreference(); @@ -101,13 +106,14 @@ public class DeviceTest { Mockito.when(context.getSharedPreferences(eq("unpairedTestDevice"), eq(Context.MODE_PRIVATE))).thenReturn(untrustedSettings); //Default shared prefs, including our own private key - PowerMockito.mockStatic(PreferenceManager.class); + preferenceManager = Mockito.mockStatic(PreferenceManager.class); MockSharedPreference defaultSettings = new MockSharedPreference(); - PowerMockito.when(PreferenceManager.getDefaultSharedPreferences(any())).thenReturn(defaultSettings); + preferenceManager.when(() -> PreferenceManager.getDefaultSharedPreferences(any(Context.class))).thenReturn(defaultSettings); + RsaHelper.initialiseRsaKeys(context); - PowerMockito.mockStatic(ContextCompat.class); - PowerMockito.when(ContextCompat.getSystemService(context, NotificationManager.class)).thenReturn(Mockito.mock(NotificationManager.class)); + contextCompat = Mockito.mockStatic(ContextCompat.class); + contextCompat.when(() -> ContextCompat.getSystemService(context, NotificationManager.class)).thenReturn(Mockito.mock(NotificationManager.class)); } @Test @@ -151,7 +157,8 @@ public class DeviceTest { assertNotNull(device.deviceInfo.certificate); } - public void testPairingDone() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, CertificateException { + @Test + public void testPairingDone() throws CertificateException { NetworkPacket fakeNetworkPacket = new NetworkPacket(NetworkPacket.PACKET_TYPE_IDENTITY); String deviceId = "unpairedTestDevice"; @@ -194,9 +201,7 @@ public class DeviceTest { assertEquals(device.getDeviceType(), DeviceType.PHONE); assertNotNull(device.deviceInfo.certificate); - Method method = PairingHandler.class.getDeclaredMethod("pairingDone"); - method.setAccessible(true); - method.invoke(device.pairingHandler); + device.pairingHandler.pairingDone(); assertTrue(device.isPaired());