[英]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. I am attempting to decode a Base64 encoded string in Android using thehttp://developer.android.com/reference/android/util/Base64.html class.
Both the encodeToString and decode methods are returning null, and I have no idea what's wrong, here's my code for the decode: 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");
I'm running Android API 23.1.0我正在运行 Android API 23.1.0
I had the same problem in my unit tests. 我的单元测试中遇到了同样的问题。 I didn't realize the Base64 class I'm using is a part of the Android API, therefore
我没有意识到我正在使用的Base64类是Android API的一部分,因此
You can't use android.util.Base64 in a regular JUnit test, it must be an Instrumentation test. 您不能在常规JUnit测试中使用android.util.Base64,它必须是Instrumentation测试。
However, if you really want it as a unit test, you could use the Apache Commons Base64 class instead. 但是,如果您真的希望将其作为单元测试,则可以使用Apache Commons Base64类。 Include it in Gradle build:
将它包含在Gradle构建中:
// https://mvnrepository.com/artifact/org.apache.commons/commons-collections4
compile group: 'org.apache.commons', name: 'commons-collections4', version: '4.1'
And then slightly different usage, 然后用法略有不同,
Base64. Base64编码。 encodeBase64String(byte[] binaryData)
encodeBase64String(byte [] binaryData)
Base64. Base64编码。 decodeBase64(String base64String)
decodeBase64(String base64String)
Follow up o android tutorials and unit test notes while you need just Unit tests without use of some android libs 跟进o android教程和单元测试笔记,而你只需要单元测试而不使用一些android库
In your case you're depending on android.Base64. 在你的情况下,你依赖于android.Base64。 I had similar issue and moving test classes from
src/test
-> src/androidTest
worked. 我有类似的问题,并从
src/test
- > src/androidTest
移动测试类工作。 Those tests are run on virtual machine or real android device. 这些测试在虚拟机或真正的Android设备上运行。 I didn't notice the diff at the first look.
第一次看时我没注意到差异。
You can use the Robolectric Runner 您可以使用Robolectric Runner
Add the dependency in your build.gradle
: 在
build.gradle
添加依赖build.gradle
:
testCompile 'org.robolectric:robolectric:XXX'
Add this line in your testing class: 在测试类中添加以下行:
import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @RunWith(RobolectricTestRunner.class) public class MyTestingClassTest { ... }
As discussed, android.util.Base64.decode is returning a null in test harness because of this setting in the build file: 如上所述,由于构建文件中的此设置,android.util.Base64.decode在测试工具中返回null:
testOptions {
unitTests.returnDefaultValues = true
}
To avoid including other libraries you could fall back on java.util.Base64, which is only available in Java8 and on Android 26 and above. 为了避免包含其他库,您可以使用java.util.Base64,这只能在Java8和Android 26及更高版本中使用。 If you already target 26+ then just switch to this method, but if you have to target earlier SDKs you could check for the null return and call a test-harness method instead:
如果您已经定位到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)
}
I would rather do this than pull in additional library dependencies, but YMMV. 我宁愿这样做而不是引入额外的库依赖,但是YMMV。
What works with me is to mock Base64.decode method using mockk对我有用的是使用 mockk 模拟 Base64.decode 方法
mockkStatic(Base64::class)
every { Base64.decode(any<String>(),Base64.DEFAULT) } returns byteArrayOf()
What I ended up doing was a wrapper.我最终做的是一个包装器。 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).
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.