【问题标题】:Mocking method calls using power mockito - org.powermock.api.mockito.ClassNotPreparedException使用 power mockito 模拟方法调用 - org.powermock.api.mockito.ClassNotPreparedException
【发布时间】:2017-01-17 06:25:45
【问题描述】:

我有一个图像加载器类,我需要在其中测试一些静态方法。由于 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' 注释的类。

下面是我的完整代码。

要测试的代码:

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

测试类代码

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 依赖项

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'

【问题讨论】:

  • 向我们展示您的导入
  • @JEY Imports 添加。测试类和要测试的类都使用相同的导入。
  • 你使用的是 junit 还是 testng ?因为测试注解是从 TestNG 导入的。
  • @JEY 我将导入从 TestNG 更改为 Junit,现在我收到如下错误。 " ================================================= 默认套件运行的测试总数:0,失败:0,跳过:0 ===================================== ========== 进程以退出代码 0 空测试套件完成。“我不确定要使用哪个测试框架。
  • 看看developer.android.com/studio/test/index.html,了解如何创建和运行单元测试。

标签: android unit-testing junit mockito powermock


【解决方案1】:

简短的回答你不能。这里来自FAQ

Mockito 有什么限制

  • 无法模拟最终课程
  • 无法模拟静态方法
  • 无法模拟最终方法 - 它们的真实行为会毫无例外地执行。 Mockito 无法警告您模拟最终方法,所以 保持警惕。

有关此限制的更多信息:

我可以模拟静态方法吗?

没有。 Mockito 更喜欢面向对象和依赖注入 难以理解和更改的静态程序代码。如果你 处理可怕的遗留代码,你可以使用 JMockit 或 Powermock 来模拟 静态方法。

如果你想使用 PowerMock 试试这样:

@RunWith(PowerMockRunner.class)
@PrepareForTest( { Base64.class })
public class YourTestCase {
    @Test
    public void testStatic() {
        mockStatic(Base64.class);
        when(Base64.encodeToString(argument)).thenReturn("expected result");
    }
}

编辑: 在Mockito 2 it's now possible to mock final Class and final Method。这是一个可选的选项。您需要创建文件src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker,内容如下:

mock-maker-inline

编辑 2: 由于 Mockito 3.4.0 现在也可以mock static method

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 开始,您还可以mock object construction

【讨论】:

  • 这个答案一点用都没有。您基本上重申了问题提到的内容:“由于 Mockito 不支持静态方法,因此我切换到 Power Mockito”,然后在您提到 PowerMock 时,您举了一个示例,该示例基本上重复了他在问题示例代码中的内容。
  • 这个问题已经被多次编辑,随着时间的推移包含我的部分答案。你可以投反对票。
  • 抱歉,在添加我的评论之前,我应该考虑到问题已被编辑。
【解决方案2】:

根据您的导入,您正在为您的测试使用 TestNG 框架,并为 PowerMock 使用 Junit 模块。我认为这就是发生冲突的地方。您可以按照这篇 https://www.baeldung.com/intro-to-powermock 文章设置 Junit4 以使用 powermock。或者,如果您打算继续使用 TestNG 作为您的测试框架,您可能需要在 Google 上设置 TestNG 以使用 powermock。

【讨论】:

    【解决方案3】:

    我遇到了类似的问题,并通过使用 PowerMockTestCase 扩展类来修复它。

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({Base64.class})
    public class ImageLoaderTest extends PowerMockTestCase{
    
    }
    

    【讨论】:

      猜你喜欢
      • 2015-12-13
      • 2017-01-29
      • 2015-11-04
      • 2017-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      相关资源
      最近更新 更多