[英]How do I unit test Android code that has View Animators?
I have an instance where a couple buttons are shown and hidden depending on which page in a ViewPager is being shown.我有一个实例,其中显示和隐藏了几个按钮,具体取决于显示的是 ViewPager 中的哪个页面。 The are shown and hidden with Animators.
使用动画师显示和隐藏。 Is there a way to check for/delay unit testing until this has been completed?
有没有办法在完成之前检查/延迟单元测试?
I'm using Robolectric since that's probably relevant.我正在使用 Robolectric,因为这可能是相关的。 I tried calling
Robolectric.runUiThreadTasksIncludingDelayedTasks();
我尝试调用
Robolectric.runUiThreadTasksIncludingDelayedTasks();
but this didn't seem to fix anything.但这似乎没有解决任何问题。
The animation code is as follows:动画代码如下:
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();
}
I think you could solve this problem rearranging the approach.我认为你可以通过重新安排方法来解决这个问题。 This is, by extracting the SimpleAnimatorListener to a protected variable, and then unit test based on that.
这是通过将 SimpleAnimatorListener 提取到受保护的变量,然后基于它进行单元测试。 Something like:
就像是:
@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();
}
And then on your test:然后在你的测试中:
private void shouldShowViewWhenShowIsTrue() {
View mockedView = Mockito.mock(View.class);
SimpleAnimatorListener animationListener = getAnimationListener(true, mockedView);
animationListener.onAnimationStart(null);
Mockito.verify(mockedView).setVisibility(View.VISIBLE);
}
Even better could be to have instead of a method like getAnimationListener(), would be to create a FadeAnimationListener that would extend SimpleAnimatorListener, and put the animation logic there.更好的方法是创建一个 FadeAnimationListener,而不是像 getAnimationListener() 这样的方法,它可以扩展 SimpleAnimatorListener,并将动画逻辑放在那里。
Hope this helps!希望这可以帮助!
I ended up creating an AnimationUtility interface and a real and fake implementations.我最终创建了一个 AnimationUtility 接口和一个真实和虚假的实现。 The fake implementation immediately set the view to visible/hidden instead of doing the animation.
假实现立即将视图设置为可见/隐藏而不是执行动画。 I dynamically inject the real/fake one depending on the proper context.
我根据适当的上下文动态注入真/假。
Here I put my solution based on ValueAnimator
classes.在这里,我提出了基于
ValueAnimator
类的解决方案。 I use mockk library.我使用模拟库。
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 }
}
}
}
For ViewPropertyAnimator
you could try similar approach对于
ViewPropertyAnimator
您可以尝试类似的方法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.