问题
I am attempting to decode a Base64 encoded string in Android using the http://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:
// 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
回答1:
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
You can't use android.util.Base64 in a regular JUnit test, it must be an Instrumentation test.
However, if you really want it as a unit test, you could use the Apache Commons Base64 class instead. Include it in Gradle build:
// 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.encodeBase64String(byte[] binaryData)
Base64.decodeBase64(String base64String)
回答2:
Follow up o android tutorials and unit test notes while you need just Unit tests without use of some android libs
In your case you're depending on android.Base64. I had similar issue and moving test classes from src/test
-> src/androidTest
worked. Those tests are run on virtual machine or real android device. I didn't notice the diff at the first look.
回答3:
You can use the Robolectric Runner
Add the dependency in your
build.gradle
:testCompile 'org.robolectric:robolectric:X.X.X'
Add this line in your testing class:
import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @RunWith(RobolectricTestRunner.class) public class MyTestingClassTest { ... }
回答4:
As discussed, android.util.Base64.decode is returning a null in test harness because of this setting in the build file:
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. 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:
// 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.
来源:https://stackoverflow.com/questions/33847781/android-base64-encode-and-decode-return-null-in-unit-test