androidandroid-jetpack-composecoilandroid-jetpack-compose-testing

How to unit test if an image was loaded using Coil + Compose


I'm loading an image using Coil for Compose like below.

@Composable
fun SvgImageSample() {
    val painter = rememberAsyncImagePainter(
        model = ImageRequest.Builder(LocalContext.current)
            .decoderFactory(SvgDecoder.Factory())
            .data("https://someserver.com/SVG_image.svg")
            .size(Size.ORIGINAL)
            .build()
    )
    Image(
        painter = painter,
        modifier = Modifier.size(100.dp).testTag("myImg"),
        contentDescription = null
    )
}

The image is loaded properly. Now, I would like to write a test to check if the image was loaded. Is there any assertion out-of-the-box for that?

Something like this:

class MyTest {
    @get:Rule
    val composeTestRule = createComposeRule()

    @Test
    fun checkIfTheImageLoads() {
        composeTestRule.setContent {
            MyAppThemeTheme {
                SvgImageSample()
            }
        }
        composeTestRule.onNodeWithTag("myImg")
            .assertCoilImageIsLoaded() // <- this is what I want
    }
}

Solution

  • Another way would be to implement an EventListener and check the right events are emitted. Will save you using testTags and semantic properties in the app code.

    https://coil-kt.github.io/coil/api/coil-base/coil-base/coil/-event-listener/index.html

    A quick hacky attempt, but you could wrap this in a Composable helper that does this for any block passed in.

    @Test
    fun imageLoader() {
        var success = 0
        var errors = 0
    
        composeTestRule.setContent {
            Coil.setImageLoader(
                ImageLoader.Builder(context)
                    .eventListener(object : EventListener {
                        override fun onSuccess(
                            request: ImageRequest, 
                            result: SuccessResult
                        ) {
                            success++
                        }
    
                        override fun onError(
                            request: ImageRequest, 
                            result: ErrorResult
                        ) {
                            errors++
                        }
                    })
                    .build()
            )
            MyAppThemeTheme {
                SvgImageSample()
            }
       }
       Thread.sleep(500)
       assertThat(errors).isEqualTo(0)
       assertThat(success).isEqualTo(1)
    }