Compose: advanceTimeBy не работает с анимацией

у меня есть два Boxэс и один. Нажав на Buttonбудет переключать флаг, и это вызывает AnimatedVisibilityанимация на этих коробках.

Код

      @Composable
fun TestBox() {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        var flag by remember { mutableStateOf(false) }
        AnimatedVisibility(
            visible = !flag,
            enter = slideInHorizontally(animationSpec = tween(3000)) { it },
            exit = slideOutHorizontally(animationSpec = tween(3000)) { -it }
        ) {
            // Red box
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(Color.Red)
                    .testTag("red_box"),
            ) {}
        }

        AnimatedVisibility(
            visible = flag,
            enter = slideInHorizontally(animationSpec = tween(3000)) { it },
            exit = slideOutHorizontally(animationSpec = tween(3000)) { -it }
        ) {
            // Red box
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(Color.Green)
                    .testTag("green_box"),
            ) {}
        }

        Button(onClick = { flag = !flag }) {
            Text(text = "TOGGLE")
        }
    }
}

Вывод

Теперь я хочу написать тест, чтобы проверить, видны ли два прямоугольника в середине перехода. Поэтому я написал такой тест

      class BoxAnimationTest {
    
    
    @get:Rule
    val composeRule = createComposeRule()

    @Before
    fun beforeAll() {
        composeRule.setContent {
            TestBox()
        }
    }

    @Test
    fun firstTest() {
        with(composeRule) {
            mainClock.autoAdvance = false
            onNodeWithTag("red_box").assertExists() // red box visible
            onNodeWithTag("green_box").assertDoesNotExist() // green box shouldn't be visible
            onNodeWithText("TOGGLE").performClick() // clicking toggle button
            
            mainClock.advanceTimeBy(1500) // and advance time to half of total duration (3000ms)
            onNodeWithTag("green_box").assertExists() // now both green and 
            onNodeWithTag("red_box").assertExists() // [FAILED] red should be visible
            
            mainClock.advanceTimeBy(1500) // finishing the animation
            onNodeWithTag("green_box") // now green should be visible
            onNodeWithTag("red_box").assertDoesNotExist() // but red shouldn't be
        }
    }
}

Но он терпит неудачу в onNodeWithTag("red_box").assertExists()(2-й).

      java.lang.AssertionError: Failed: assertExists.
Reason: Expected exactly '1' node but could not find any node that satisfies: (TestTag = 'red_box')

Есть идеи, почему?

1 ответ

Некоторое первоначальное расследование показало, что анимация из AnimatedVisibilityникогда не добавлялись в , потому что measure()не был вызван, и анимация слайдов инициализируется во время измерения. В итоге у нас осталась пустая Transitionчто закончилось сразу. Вот почему тест провалился. Обратите внимание, что добавление advanceTimeByFrame()до advanceTimeBy(1500)кажется, позволяет пройти тест. Это может быть полезно для сужения причины.