Вызывание методов вызова с использованием power mockito - org.powermock.api.mockito.ClassNotPreparedException

У меня есть класс загрузчика изображений, и мне нужно проверить некоторые статические методы в нем. Поскольку Mockito не поддерживает статические методы, я переключился на Power Mockito. Но статический метод, который я тестирую, имеет вызов метода

 Base64.encodeToString(byteArray, Base64.DEFAULT);

Чтобы издеваться над этим, я использую метод mockStatic, как показано ниже, с аннотацией @PrepareForTest.

 PowerMockito.mockStatic(Base64.class);

Но студия Android возвращает мне все еще возвращающую мне ошибку, как показано ниже.

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'

Ответы

Ответ 1

Короткий ответ вы не можете. Вот из FAQ:

Каковы ограничения 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 теперь можно издеваться над финальным классом и финальным методом. Это опция выбора. Вам необходимо создать файл src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker со следующим содержимым:

mock-maker-inline

Ответ 2

В дополнение к @PrepareForTest также использовать extends PowerMockTestCase

Пример: @PrepareForTest({Base64.class}) public class ImageLoaderTest extends PowerMockTestCase

Ответ 3

На самом деле тривиально, я думаю, что вы неправильно вызываете prepareForTest. Это должно быть prepareForTest(Base64.class) not prepareForTest({Base64.class}) (обратите внимание на скользящие фигурные скобки в вашем коде). Учитывая ошибку, которую вы получаете, я думаю, что это важно.