Reputation: 5348
I have an image loader class and i need to test some static methods in it. Since Mockito does not support static methods i switched to Power Mockito. But the static method i am testing has a method call
Base64.encodeToString(byteArray, Base64.DEFAULT);
To mock this i am using mockStatic method as below with @PrepareForTest annotation.
PowerMockito.mockStatic(Base64.class);
But Android studio is returning me still returning me an error as below.
org.powermock.api.mockito.ClassNotPreparedException: The class android.util.Base64 not prepared for test. To prepare this class, add class to the '@PrepareForTest' annotation.
Below is my complete code.
Code to be tested:
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Base64;
import android.widget.ImageView;
public static String convertBitmapToBase64(Bitmap imageBitmap, boolean withCompression) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
imageBitmap.compress(Bitmap.CompressFormat.PNG, 120, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
return Base64.encodeToString(byteArray, Base64.DEFAULT);
}
Test class code
import android.graphics.Bitmap;
import android.util.Base64;
import org.junit.Before;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.testng.annotations.Test;
@RunWith(PowerMockRunner.class)
@PrepareForTest({Base64.class})
public class ImageLoaderTest {
@Test
public void testConvertBitmap(){
byte[] array = new byte[20];
PowerMockito.mockStatic(Base64.class);
PowerMockito.when(Base64.encodeToString(array, Base64.DEFAULT)).thenReturn("asdfghjkl");
Bitmap mockedBitmap= PowerMockito.mock(Bitmap.class);
String output = ImageLoaderUtils.convertBitmapToBase64(mockedBitmap);
assert (!output.isEmpty());
}
}
Gradle dependencies
testCompile 'junit:junit:4.12'
testCompile 'org.powermock:powermock:1.6.5'
testCompile 'org.powermock:powermock-module-junit4:1.6.5'
testCompile 'org.powermock:powermock-api-mockito:1.6.5'
Upvotes: 30
Views: 63235
Reputation: 873
I faced a similar issue and fixed it by extending the class with PowerMockTestCase.
@RunWith(PowerMockRunner.class)
@PrepareForTest({Base64.class})
public class ImageLoaderTest extends PowerMockTestCase{
}
Upvotes: -1
Reputation: 1
Based on your imports, you are using TestNG framework for your test and Junit module for PowerMock. I think that's where the conflict arises. You can follow this https://www.baeldung.com/intro-to-powermock article to setup Junit4 to work with powermock. Or you may need to google setup TestNG to work with powermock if you intend to keep using TestNG as your testing framework.
Upvotes: 0
Reputation: 7123
Short answer you can't. Here from the FAQ:
What are the limitations of Mockito
- Cannot mock final classes
- Cannot mock static methods
- Cannot mock final methods - their real behavior is executed without any exception. Mockito cannot warn you about mocking final methods so be vigilant.
Further information about this limitation:
Can I mock static methods?
No. Mockito prefers object orientation and dependency injection over static, procedural code that is hard to understand & change. If you deal with scary legacy code you can use JMockit or Powermock to mock static methods.
If you want to use PowerMock try like this:
@RunWith(PowerMockRunner.class)
@PrepareForTest( { Base64.class })
public class YourTestCase {
@Test
public void testStatic() {
mockStatic(Base64.class);
when(Base64.encodeToString(argument)).thenReturn("expected result");
}
}
EDIT:
In Mockito 2 it's now possible to mock final Class and final Method. It's an opt-in option. You need to create the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
with the following content:
mock-maker-inline
EDIT 2: Since Mockito 3.4.0 its now possible to mock static method too:
try (MockedStatic mocked = mockStatic(Base64.class)) {
mocked.when(() -> Base64.encodeToString(eq(array), eq(Base64.DEFAULT))).thenReturn("bar");
assertEquals("bar", Base64.encodeToString(array, Base64.DEFAULT));
mocked.verify(() -> Base64.encodeToString(any(), anyIn());
}
Furthermore you can directly add as a dependency org.mockito:mockito-inline:+
and avoid manually create the or.mockito.plugins.MockMaker file
Since Mockito 3.5.0 you can also mock object construction.
Upvotes: 19