Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 413
O.O.Balance Avatar asked Mar 05 '18 11:03

O.O.Balance


3 Answers

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...
}

enter image description here

like image 183
ruchkin Avatar answered Oct 20 '22 03:10

ruchkin


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.

like image 8
O.O.Balance Avatar answered Oct 20 '22 04:10

O.O.Balance


With the newer versions of Mockito you can also mock static methods. No need for powermockito anymore:

In gradle:

testImplementation "org.mockito:mockito-inline:4.0.0"
testImplementation "org.mockito.kotlin:mockito-kotlin:4.0.0"

In kotlin:

mockStatic(Base64::class.java)
`when`(Base64.encode(any(), anyInt())).thenAnswer { invocation ->
    java.util.Base64.getMimeEncoder().encode(invocation.arguments[0] as ByteArray)
}
`when`(Base64.decode(anyString(), anyInt())).thenAnswer { invocation ->
    java.util.Base64.getMimeDecoder().decode(invocation.arguments[0] as String)
}
like image 2
Jeruntu Avatar answered Oct 20 '22 04:10

Jeruntu