'How to mock Base64 in Android?
I am writing a Unit test for a class that uses android.util.Base64
and I get this error:
java.lang.RuntimeException: Method encode in android.util.Base64 not mocked. See http://g.co/androidstudio/not-mocked for details.
at android.util.Base64.encode(Base64.java)
This is the code using the encode()
method:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// [write some data to the stream]
byte[] base64Bytes = Base64.encode(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
Now I understand that I can't use Android library classes in my Unit tests. But how do I correctly mock Base64
so I can write a correct Unit test for my class?
Solution 1:[1]
Based on the comments by Nkosi and Christopher, I have found a solution. I used PowerMock to mock the static methods of Base64
:
PowerMockito.mockStatic(Base64.class);
when(Base64.encode(any(), anyInt())).thenAnswer(invocation -> java.util.Base64.getEncoder().encode((byte[]) invocation.getArguments()[0]));
when(Base64.decode(anyString(), anyInt())).thenAnswer(invocation -> java.util.Base64.getMimeDecoder().decode((String) invocation.getArguments()[0]));
And in my build.gradle
I had to add:
testImplementation "org.powermock:powermock-module-junit4:1.7.4"
testImplementation "org.powermock:powermock-api-mockito2:1.7.4"
Note that not every version of Powermock works with every version of Mockito. The version I used here is supposed to work with Mockito 2.8.0-2.8.9
, and I have no issues. However, support for Mockito 2 is still experimental. There is a table detailing the compatible versions on the project's wiki.
Solution 2:[2]
I'm late but maybe that will help somebody. For JUnit you can mock up the class without any third party lib. Just create a file Base64.java inside app/src/test/java/android/util with contents:
package android.util;
public class Base64 {
public static String encodeToString(byte[] input, int flags) {
return java.util.Base64.getEncoder().encodeToString(input);
}
public static byte[] decode(String str, int flags) {
return java.util.Base64.getDecoder().decode(str);
}
// add other methods if required...
}
Solution 3:[3]
For Kotlin, you may use:
package android.util
import java.util.Base64
public object Base64 {
@JvmStatic
public fun encodeToString(input: ByteArray?, flags: Int): String {
return Base64.getEncoder().encodeToString(input)
}
@JvmStatic
public fun decode(str: String?, flags: Int): ByteArray {
return Base64.getDecoder().decode(str)
}
}
Solution 4:[4]
If you run a test that calls an API from the Android SDK that you do not mock, you'll receive an error that says this method is not mocked. That's because the android.jar file used to run unit tests does not contain any actual code (those APIs are provided only by the Android system image on a device). Replace with java Base64.getDecoder().decode()
.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Nico |
Solution 4 | ouflak |