From a8d2636f669e3d9db5d85ea739f6770386403e7c Mon Sep 17 00:00:00 2001 From: Satoshi Qazi Muhammed Date: Fri, 10 Jul 2026 09:36:41 -0700 Subject: [PATCH] fix: use raw org.mockito.Mockito statics instead of test_shared wrappers Root cause of 'eq(...) must not be null' NPE: test_shared's eq()/any()/ argThat() are thin Kotlin wrappers with a declared non-null generic return type T. Mockito.eq()/any() genuinely return null at runtime (that's how their matcher-stack recording works) - fine when called directly from Kotlin (a raw Java static call's return is a platform type, no null-check inserted), but going through a Kotlin-declared wrapper whose T infers as non-null at the call site (e.g. eq(baseUrl: String) here) gets a compiler-inserted null-check on the wrapper's return, which then fires. Scoped this fix to this test file only rather than touching test_shared's shared implementation, which every other module's tests also depend on. --- .../RealTronTransactionServiceTest.kt | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/feature-wallet-impl/src/test/java/io/novafoundation/nova/feature_wallet_impl/data/network/tron/transaction/RealTronTransactionServiceTest.kt b/feature-wallet-impl/src/test/java/io/novafoundation/nova/feature_wallet_impl/data/network/tron/transaction/RealTronTransactionServiceTest.kt index 3bfbd1a7..8f5b9ab1 100644 --- a/feature-wallet-impl/src/test/java/io/novafoundation/nova/feature_wallet_impl/data/network/tron/transaction/RealTronTransactionServiceTest.kt +++ b/feature-wallet-impl/src/test/java/io/novafoundation/nova/feature_wallet_impl/data/network/tron/transaction/RealTronTransactionServiceTest.kt @@ -15,10 +15,6 @@ import io.novafoundation.nova.feature_wallet_impl.data.network.tron.TronGridApi import io.novafoundation.nova.feature_wallet_impl.data.network.tron.model.TronAccountResourceResponse import io.novafoundation.nova.feature_wallet_impl.data.network.tron.model.TronUnsignedTransactionResponse import io.novafoundation.nova.runtime.multiNetwork.chain.model.Chain -import io.novafoundation.nova.test_shared.any -import io.novafoundation.nova.test_shared.argThat -import io.novafoundation.nova.test_shared.eq -import io.novafoundation.nova.test_shared.whenever import io.novasama.substrate_sdk_android.encrypt.SignatureWrapper import io.novasama.substrate_sdk_android.extensions.fromHex import io.novasama.substrate_sdk_android.extensions.toHexString @@ -31,11 +27,25 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.any +import org.mockito.Mockito.argThat +import org.mockito.Mockito.eq import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnitRunner import java.math.BigInteger +// Deliberately NOT using io.novafoundation.nova.test_shared's eq/any/argThat/whenever here: those are thin +// Kotlin wrappers around the raw org.mockito.Mockito statics, and a Kotlin function with a declared non-null +// generic return type T gets a compiler-inserted null-check on that return value whenever T is inferred as +// non-null at the call site (e.g. eq(baseUrl: String) here) - crashing with "eq(...) must not be null", since +// Mockito.eq()/any() genuinely return null at runtime (that's how their matcher-stack recording works). Calling +// org.mockito.Mockito's statics directly avoids this: Kotlin treats a direct Java static call's return as a +// platform type (T!) and does not insert that check. Fixing test_shared itself would apply project-wide and +// wasn't attempted here (shared-infra change out of scope for this test file). +private fun whenever(methodCall: T?) = Mockito.`when`(methodCall) + /** * Covers the native-TRX branch of [RealTronTransactionService.transact] - the sign/broadcast pipeline this class' * own doc comment describes (sha256(raw_data) signed via the existing Ethereum-style ECDSA-raw-hash primitive,