如何对具有View Animators的Android代码进行单元测试?

时间:2014-05-05 20:27:02

标签: android unit-testing robolectric objectanimator

我有一个实例,其中显示和隐藏了几个按钮,具体取决于ViewPager中的哪个页面正在显示。使用Animators显示和隐藏。有没有办法检查/延迟单元测试,直到完成为止?

我使用的是Robolectric,因为这可能是相关的。我试着打电话给Robolectric.runUiThreadTasksIncludingDelayedTasks();,但这似乎没有解决任何问题。

动画代码如下:

public static void regularFadeView(final boolean show, final View view) {
    view.animate()
            .setInterpolator(mDecelerateInterpolator)
            .alpha(show ? 1 : 0)
            .setListener(new SimpleAnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    if (show) view.setVisibility(View.VISIBLE);
                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    if (!show) view.setVisibility(View.INVISIBLE);
                }
            })
            .start();
}

3 个答案:

答案 0 :(得分:5)

我认为你可以解决这个问题,重新安排方法。这是通过将SimpleAnimatorListener提取到受保护变量,然后基于该单元进行单元测试。类似的东西:

@VisibleForTesting
SimpleAnimatorListener getAnimationListener(boolean show, View view) {
   return new SimpleAnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            if (show) view.setVisibility(View.VISIBLE);
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            if (!show) view.setVisibility(View.INVISIBLE);
        }
    }

public static void regularFadeView(boolean show, View view) {
     view.animate()
        .setInterpolator(mDecelerateInterpolator)
        .alpha(show ? 1 : 0)
        .setListener(getAnimationListener(show, view))
        .start();
}

然后进行测试:

private void shouldShowViewWhenShowIsTrue() {
     View mockedView = Mockito.mock(View.class);
     SimpleAnimatorListener animationListener = getAnimationListener(true, mockedView);
     animationListener.onAnimationStart(null);
     Mockito.verify(mockedView).setVisibility(View.VISIBLE);
}

更好的方法是使用getAnimationListener()等方法来创建一个扩展SimpleAnimatorListener的FadeAnimationListener,并将动画逻辑放在那里。

希望这有帮助!

答案 1 :(得分:2)

我最终创建了一个AnimationUtility接口以及一个真实和虚假的实现。假实现立即将视图设置为可见/隐藏而不是动画。我根据适当的上下文动态注入真/假的。

答案 2 :(得分:0)

在这里,我将自己的解决方案基于ValueAnimator类。我使用mockk库。

fun mockObjectAnimators() {
    mockkStatic(ObjectAnimator::class)
    val targetSlot = slot<Any>()
    val propertySlot = slot<String>()
    every {
        ObjectAnimator.ofFloat(capture(targetSlot), capture(propertySlot), *anyFloatVararg())
    } answers {
        spyk(
            ObjectAnimator().apply {
                target = targetSlot.captured
                duration = 0L
                setPropertyName(propertySlot.captured)
            }
        ).also { spy ->
            every { spy.start() } answers {
                spy.listeners.forEach { it.onAnimationStart(spy) }
                spy.listeners.forEach { it.onAnimationEnd(spy) }
            }
            every { spy.setDuration(any()) } answers { spy }
        }
    }
}

对于ViewPropertyAnimator,您可以尝试类似的方法