Как создать макет растрового изображения с помощью mockk, не влияя на bitmap.compress в будущих тестах

#android #kotlin #android-testing #mockk

#Android #kotlin #android-тестирование #mockk

Вопрос:

Как мне смоделировать растровое изображение, чтобы оно не нарушало растровые изображения в будущих тестах? Давайте рассмотрим следующий упрощенный пример…

 class FileHelper @Inject constructor(private val application: Application) {
    fun saveBitmapToTempDirectory(bitmap: Bitmap, filename: String, format: Bitmap.CompressFormat): File {
        val tempDirectory = File(application.cacheDir, "images").apply { mkdirs() }
        val file = File(tempDirectory, "$filename.${format.name.toLowerCase()}")
        FileOutputStream(file).use { outStream ->
            bitmap.compress(format, 100, outStream)
        }
        return file
    }
}
  

Допустим, класс may test выглядит следующим образом…

 @RunWith(AndroidJUnit4::class)
class FileHelperTest {

    @Test
    fun otherTest(){
//        When I uncomment the next line, I get NoSuchMethodException: checkRecycled in testSaveBitmapToTempDirectoryWithSuccess()
//        val mockBitmap: Bitmap = mockk()
//        Do stuff using a mockBitmap

//        The following block also causes the same issue (even with a real decoded Bitmap).
//        mockkStatic(BitmapFactory::class)
//        every {
//            BitmapFactory.decodeStream(mockInputStream)
//        } returns realDecodedBitmap
//        unmockkStatic(BitmapFactory::class)

//        None of the following work:
//        unmockkAll()
//        clearAllMocks()
//        unmockkStatic(Bitmap::class)
//        clearMocks(mockBitmap)
//        clearStaticMockk(Bitmap::class)
    }

    @Test
    fun testSaveBitmapToTempDirectoryWithSuccess() {
        val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as Application
        val file = FileHelper(application).saveBitmapToTempDirectory(
            BitmapFactory.decodeResource(application.resources, R.drawable.mypic),
            "bitmap",
            Bitmap.CompressFormat.PNG
        )
        assertTrue(file.absolutePath.endsWith("bitmap.png"))
    }
}
  

testSaveBitmapToTempDirectoryWithSuccess() проходит, если я запускаю его один. Если я включу строку, которая имитирует растровое изображение ( val mockBitmap: Bitmap = mockk() ), то testSaveBitmapToTempDirectoryWithSuccess() произойдет сбой при совместном запуске всех тестов. bitmap.compress() выдает NoSuchMethodException: checkRecycled

Аналогично, если другой тестовый класс создает макет растрового изображения и запускается как группа с этим тестовым классом, то testSaveBitmapToTempDirectoryWithSuccess() произойдет сбой по той же причине.

Как мне справиться с этой ситуацией? В некоторых тестах я хотел бы иметь макет растрового изображения. В других тестах я бы хотел сжать реальное изображение.

Комментарии:

1. У вас есть тест, который успешно создает экземпляр Bitmap и проходит. Почему вы хотите смоделировать его другим методом в том же тестовом файле?

2. Хороший вопрос. Этот пример представляет собой упрощенную версию того, с чем я столкнулся при запуске нескольких тестовых файлов. Проблема возникла, когда у тестового класса A был макет растрового изображения, а тестовый класс B сделал что-то похожее на то, что показано в примере, и я запускаю тесты A и B как группу. В основном я просто поместил его в один тестовый класс, чтобы упростить пример, и я удалил кучу другого кода, чтобы изолировать его от того, что вызывало проблему.

3. Понял. Я бы рекомендовал не издеваться над такими вещами, как Bitmaps: это конечный класс, следовательно, mockk должен выполнять странные манипуляции с байт-кодом, чтобы издеваться над ним. Просто создайте тестовые экземпляры так, как вы уже делаете.

4. unmockkAll должно было быть возвращено в исходное состояние. Также unmockkObject подходит для возврата mockk . Если это не работает, пожалуйста, отправьте сообщение о проблеме с подробным описанием на github.com/mockk/issues

5. Для всех, кому это интересно… github.com/mockk/mockk/issues/270