diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt
new file mode 100644
index 0000000000..2970dec29a
--- /dev/null
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/Util.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk
+
+import junit.framework.TestCase.fail
+
+/**
+ * Will fail the test if invoking [block] is not throwing a Throwable.
+ *
+ * @param message the failure message, if the block does not throw any Throwable
+ * @param failureBlock a Lambda to be able to do extra check on the thrown Throwable
+ * @param block the block to test
+ */
+internal suspend fun mustFail(
+        message: String = "must fail",
+        failureBlock: ((Throwable) -> Unit)? = null,
+        block: suspend () -> Unit,
+) {
+    val isSuccess = try {
+        block.invoke()
+        true
+    } catch (throwable: Throwable) {
+        failureBlock?.invoke(throwable)
+        false
+    }
+
+    if (isSuccess) {
+        fail(message)
+    }
+}
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt
index 38597269cb..552936971f 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt
@@ -62,6 +62,7 @@ import org.matrix.android.sdk.common.RetryTestRule
 import org.matrix.android.sdk.common.SessionTestParams
 import org.matrix.android.sdk.common.TestConstants
 import org.matrix.android.sdk.common.TestMatrixCallback
+import org.matrix.android.sdk.mustFail
 import java.util.concurrent.CountDownLatch
 
 @RunWith(JUnit4::class)
@@ -525,10 +526,8 @@ class E2eeSanityTests : InstrumentedTest {
 
         // Confirm we can decrypt one but not the other
         testHelper.runBlockingTest {
-            try {
+            mustFail(message = "Should not be able to decrypt event") {
                 newBobSession.cryptoService().decryptEvent(firstEventNewBobPov.root, "")
-                fail("Should not be able to decrypt event")
-            } catch (_: MXCryptoError) {
             }
         }
 
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt
index 1bd2a46381..895f95aeac 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt
@@ -21,7 +21,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
 import junit.framework.TestCase.assertNotNull
 import junit.framework.TestCase.assertTrue
-import junit.framework.TestCase.fail
 import org.amshove.kluent.internal.assertEquals
 import org.junit.Assert
 import org.junit.Assert.assertNull
@@ -47,6 +46,7 @@ import org.matrix.android.sdk.common.CryptoTestHelper
 import org.matrix.android.sdk.common.RetryTestRule
 import org.matrix.android.sdk.common.SessionTestParams
 import org.matrix.android.sdk.common.TestConstants
+import org.matrix.android.sdk.mustFail
 
 @RunWith(AndroidJUnit4::class)
 @FixMethodOrder(MethodSorters.JVM)
@@ -95,12 +95,10 @@ class KeyShareTests : InstrumentedTest {
         assertNotNull(receivedEvent)
         assert(receivedEvent!!.isEncrypted())
 
-        try {
-            commonTestHelper.runBlockingTest {
+        commonTestHelper.runBlockingTest {
+            mustFail {
                 aliceSession2.cryptoService().decryptEvent(receivedEvent.root, "foo")
             }
-            fail("should fail")
-        } catch (failure: Throwable) {
         }
 
         val outgoingRequestsBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequests()
@@ -168,12 +166,10 @@ class KeyShareTests : InstrumentedTest {
             }
         }
 
-        try {
-            commonTestHelper.runBlockingTest {
+        commonTestHelper.runBlockingTest {
+            mustFail {
                 aliceSession2.cryptoService().decryptEvent(receivedEvent.root, "foo")
             }
-            fail("should fail")
-        } catch (failure: Throwable) {
         }
 
         // Mark the device as trusted
diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt
index 1c3c6c46e7..13133b726c 100644
--- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt
+++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt
@@ -42,6 +42,7 @@ import org.matrix.android.sdk.common.MockOkHttpInterceptor
 import org.matrix.android.sdk.common.RetryTestRule
 import org.matrix.android.sdk.common.SessionTestParams
 import org.matrix.android.sdk.common.TestConstants
+import org.matrix.android.sdk.mustFail
 
 @RunWith(AndroidJUnit4::class)
 @FixMethodOrder(MethodSorters.JVM)
@@ -96,17 +97,19 @@ class WithHeldTests : InstrumentedTest {
         // =============================
 
         // Bob should not be able to decrypt because the keys is withheld
-        try {
-            // .. might need to wait a bit for stability?
-            testHelper.runBlockingTest {
+        // .. might need to wait a bit for stability?
+        testHelper.runBlockingTest {
+            mustFail(
+                    message = "This session should not be able to decrypt",
+                    failureBlock = { failure ->
+                        val type = (failure as MXCryptoError.Base).errorType
+                        val technicalMessage = failure.technicalMessage
+                        Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type)
+                        Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage)
+                    }
+            ) {
                 bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "")
             }
-            Assert.fail("This session should not be able to decrypt")
-        } catch (failure: Throwable) {
-            val type = (failure as MXCryptoError.Base).errorType
-            val technicalMessage = failure.technicalMessage
-            Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type)
-            Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage)
         }
 
         // Let's see if the reply we got from bob first session is unverified
@@ -137,17 +140,18 @@ class WithHeldTests : InstrumentedTest {
         }
 
         // Previous message should still be undecryptable (partially withheld session)
-        try {
-            // .. might need to wait a bit for stability?
-            testHelper.runBlockingTest {
+        // .. might need to wait a bit for stability?
+        testHelper.runBlockingTest {
+            mustFail(
+                    message = "This session should not be able to decrypt",
+                    failureBlock = { failure ->
+                        val type = (failure as MXCryptoError.Base).errorType
+                        val technicalMessage = failure.technicalMessage
+                        Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type)
+                        Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage)
+                    }) {
                 bobUnverifiedSession.cryptoService().decryptEvent(eventBobPOV.root, "")
             }
-            Assert.fail("This session should not be able to decrypt")
-        } catch (failure: Throwable) {
-            val type = (failure as MXCryptoError.Base).errorType
-            val technicalMessage = failure.technicalMessage
-            Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type)
-            Assert.assertEquals("Cause should be unverified", WithHeldCode.UNVERIFIED.value, technicalMessage)
         }
 
         testHelper.signOutAndClose(aliceSession)
@@ -190,17 +194,18 @@ class WithHeldTests : InstrumentedTest {
 
         // Previous message should still be undecryptable (partially withheld session)
         val eventBobPOV = bobSession.getRoom(testData.roomId)?.getTimelineEvent(eventId)
-        try {
-            // .. might need to wait a bit for stability?
-            testHelper.runBlockingTest {
+        // .. might need to wait a bit for stability?
+        testHelper.runBlockingTest {
+            mustFail(
+                    message = "This session should not be able to decrypt",
+                    failureBlock = { failure ->
+                        val type = (failure as MXCryptoError.Base).errorType
+                        val technicalMessage = failure.technicalMessage
+                        Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type)
+                        Assert.assertEquals("Cause should be unverified", WithHeldCode.NO_OLM.value, technicalMessage)
+                    }) {
                 bobSession.cryptoService().decryptEvent(eventBobPOV!!.root, "")
             }
-            Assert.fail("This session should not be able to decrypt")
-        } catch (failure: Throwable) {
-            val type = (failure as MXCryptoError.Base).errorType
-            val technicalMessage = failure.technicalMessage
-            Assert.assertEquals("Error should be withheld", MXCryptoError.ErrorType.KEYS_WITHHELD, type)
-            Assert.assertEquals("Cause should be unverified", WithHeldCode.NO_OLM.value, technicalMessage)
         }
 
         // Ensure that alice has marked the session to be shared with bob