簡體   English   中英

Android Base64 編碼和解碼返回 null 在單元測試中

[英]Android Base64 encode and decode return null in Unit Test

I am attempting to decode a Base64 encoded string in Android using thehttp://developer.android.com/reference/android/util/Base64.html class.

encodeToString 和 decode 方法都返回 null,我不知道出了什么問題,這是我的解碼代碼:

// Should decode to "GRC"
String friendlyNameBase64Encoded = "R1JD";

// This returns null
byte[] friendlyNameByteArray = Base64.decode(friendlyNameBase64Encoded, Base64.DEFAULT);

// Fails with NullPointerException
String friendlyName = new String(friendlyNameByteArray, "UTF-8");

我正在運行 Android API 23.1.0

我的單元測試中遇到了同樣的問題。 我沒有意識到我正在使用的Base64類是Android API的一部分,因此

您不能在常規JUnit測試中使用android.util.Base64,它必須是Instrumentation測試。

但是,如果您真的希望將其作為單元測試,則可以使用Apache Commons Base64類。 將它包含在Gradle構建中:

// https://mvnrepository.com/artifact/org.apache.commons/commons-collections4
compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.1'

然后用法略有不同,

跟進o android教程和單元測試筆記,而你只需要單元測試而不使用一些android庫

在你的情況下,你依賴於android.Base64。 我有類似的問題,並從src/test - > src/androidTest移動測試類工作。 這些測試在虛擬機或真正的Android設備上運行。 第一次看時我沒注意到差異。

您可以使用Robolectric Runner

  1. build.gradle添加依賴build.gradle

     testCompile 'org.robolectric:robolectric:XXX' 
  2. 在測試類中添加以下行:

     import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @RunWith(RobolectricTestRunner.class) public class MyTestingClassTest { ... } 

如上所述,由於構建文件中的此設置,android.util.Base64.decode在測試工具中返回null:

testOptions {
    unitTests.returnDefaultValues = true
}

為了避免包含其他庫,您可以使用java.util.Base64,這只能在Java8和Android 26及更高版本中使用。 如果您已經定位到26+,那么只需切換到此方法,但如果您必須定位早期的SDK,則可以檢查null返回並調用test-harness方法:

// Required because Android classes return null in desktop unit tests
@TargetApi(26)
private fun testHarnessDecode(s : String) : ByteArray {
    return java.util.Base64.getDecoder().decode(s)
}

我寧願這樣做而不是引入額外的庫依賴,但是YMMV。

對我有用的是使用 mockk 模擬 Base64.decode 方法

 mockkStatic(Base64::class)
 every { Base64.decode(any<String>(),Base64.DEFAULT) } returns byteArrayOf()

我最終做的是一個包裝器。 I allow the android.util.Base64 to fail and then if we are on build greater than "O" or equal to 0 (zero. meaning not an android device or no android sdk version).

 class Base64Wrapper {
    companion object {
        fun encodeToString(input : ByteArray) : String {
            return try {
                Base64.encodeToString(input, Base64.DEFAULT)
            } catch (e :Exception) {
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O || android.os.Build.VERSION.SDK_INT == 0) {
                    java.util.Base64.getEncoder().encodeToString(input)
                } else {
                    throw e;
                }
            }
        }

        fun decode(input: String) : ByteArray {
            return try {
                Base64.decode(input, Base64.DEFAULT)
            } catch (e :Exception) {
                // if build is greater or equal to "O" or is equal to 0 (zero) which means it is not a device (i.e. unit test).
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O || android.os.Build.VERSION.SDK_INT == 0) {
                    java.util.Base64.getDecoder().decode(input)
                } else {
                    throw e;
                }
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM