Showing posts with label powermock. Show all posts
Showing posts with label powermock. Show all posts

Tuesday, September 27, 2016

Mocking method calls using power mockito - org.powermock.api.mockito.ClassNotPreparedException

Leave a Comment

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' 

2 Answers

Answers 1

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");     } } 

More on powermock test sample

Answers 2

Really trivially, I think you're calling prepareForTest incorrectly. It should be prepareForTest(Base64.class) not prepareForTest({Base64.class}) (note the squiggly braces in your code). Given the error you're getting, I think that's relevant.

Read More

Monday, April 11, 2016

Can I use Cobertura on Unit Tests with PowerMock?

Leave a Comment

Problem

I am setting-up unit-test code coverage for an Android library which uses Robolectric to run the tests and PowerMock/Mockito for mock-testing.

However, running unit-tests with Cobertura results in the following Exception...

:example:testDebugUnitTest Exception in thread "Thread-5" java.lang.ExceptionInInitializerError     at com.example.package.saas.Query$RemoveWordsType.__cobertura_init(Query.java)     at com.example.package.saas.Query$RemoveWordsType.<clinit>(Query.java)     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     at java.lang.reflect.Method.invoke(Method.java:498)     at net.sourceforge.cobertura.coveragedata.TouchCollector.applyTouchesToSingleClassOnProjectData(TouchCollector.java:123)     at net.sourceforge.cobertura.coveragedata.TouchCollector.applyTouchesOnProjectData(TouchCollector.java:110)     at net.sourceforge.cobertura.coveragedata.ProjectData.saveGlobalProjectData(ProjectData.java:272)     at net.sourceforge.cobertura.coveragedata.SaveTimer.run(SaveTimer.java:33)     at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.IllegalStateException: Shutdown in progress     at java.lang.ApplicationShutdownHooks.add(ApplicationShutdownHooks.java:66)     at java.lang.Runtime.addShutdownHook(Runtime.java:211)     at net.sourceforge.cobertura.coveragedata.ProjectData.initialize(ProjectData.java:239)     at net.sourceforge.cobertura.coveragedata.ProjectData.getGlobalProjectData(ProjectData.java:209)     at net.sourceforge.cobertura.coveragedata.TouchCollector.<clinit>(TouchCollector.java:45)     ... 11 more 

...and the generated Cobertura report shows no coverage at all. Cobertura report with PowerMock


Running the same testcase without PowerMock*, the tests run fine and the coverage report is generated successfully: Cobertura report without PowerMock

​* i.e. commenting the tests using PowerMock, removing the PowerMockIgnore annotation, the PowerMockRule and the MockitoAnnotations.initMocks(this); invocation.


Investigation


Question

Is it possible to use Cobertura in conjunction with PowerMock?

  • In that case, what am I missing?
  • Otherwise, how should I measure code coverage with such a setup (Android Library + Robolectric + PowerMock)?

0 Answers

Read More