我有一个图像加载器类,我需要在其中测试一些静态方法.由于 Mockito 不支持静态方法,我切换到 Power Mockito.但是我正在测试的静态方法有一个方法调用
Base64.encodeToString(byteArray, Base64.DEFAULT);为了模拟这个,我使用 mockStatic 方法如下,带有@PrepareForTest 注释.
PowerMockito.mockStatic(Base64.class);但 Android Studio 正在返回我仍然返回如下错误.
org.powermock.api.mockito.ClassNotPreparedException:类android.util.Base64 未准备好进行测试.要准备这堂课,请添加'@PrepareForTest' 注释的类.
下面是我的完整代码.
要测试的代码:
导入android.graphics.Bitmap;导入android.graphics.BitmapFactory;导入 android.util.Base64;导入android.widget.ImageView;公共静态字符串 convertBitmapToBase64(位图 imageBitmap, boolean withCompression) {ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();imageBitmappress(Bitmap.CompressFormat.PNG, 120, byteArrayOutputStream);byte[] byteArray = byteArrayOutputStream.toByteArray();返回 Base64.encodeToString(byteArray, Base64.DEFAULT);}测试类代码
导入android.graphics.Bitmap;导入 android.util.Base64;导入 org.junit.Before;导入 org.junit.runner.RunWith;导入 org.mockito.MockitoAnnotations;导入 org.powermock.api.mockito.PowerMockito;导入 org.powermock.core.classloader.annotations.PrepareForTest;导入 org.powermock.modules.junit4.PowerMockRunner;导入 org.testng.annotations.Test;@RunWith(PowerMockRunner.class)@PrepareForTest({Base64.class})公共类 ImageLoaderTest {@测试公共无效 testConvertBitmap(){字节[]数组=新字节[20];PowerMockito.mockStatic(Base64.class);PowerMockito.when(Base64.encodeToString(array, Base64.DEFAULT)).thenReturn("asdfghjkl");位图 mockedBitmap=PowerMockito.mock(Bitmap.class);字符串输出 = ImageLoaderUtils.convertBitmapToBase64(mockedBitmap);断言 (!output.isEmpty());}}
Gradle 依赖项
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' 解决方案简答你不能.这里来自 FAQ:
Mockito 有什么限制
- 无法模拟最终课程
- 无法模拟静态方法
- 不能模拟最终方法 - 它们的真实行为会毫无例外地执行.Mockito 无法警告您模拟最终方法,所以保持警惕.
有关此限制的更多信息:
我可以模拟静态方法吗?
没有.Mockito 更喜欢面向对象和依赖注入难以理解的静态程序代码改变.如果你处理可怕的遗留代码,你可以使用 JMockit 或 Powermock 来模拟静态方法.
如果你想使用 PowerMock 试试这样:
@RunWith(PowerMockRunner.class)@PrepareForTest( { Base64.class })公共类 YourTestCase {@测试公共无效测试静态(){模拟静态(Base64.class);when(Base64.encodeToString(argument)).thenReturn("预期结果");}}在 Mockito 2 现在可以模拟最终类和最终方法.这是一个可选的选项.您需要使用以下内容创建文件 src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker:
mock-maker-inline编辑 2:由于 Mockito 3.4.0 现在可以 模拟静态方法:
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());}此外,您可以直接添加为依赖项 org.mockito:mockito-inline:+ 并避免手动创建 or.mockito.plugins.MockMaker 文件
从 Mockito 3.5.0 开始,您还可以 模拟对象构造.
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(); imageBitmappress(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'解决方案
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-inlineEDIT 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.
更多推荐
使用 power mockito 模拟方法调用
发布评论