如何为 activity 单元测试模拟自定义 ImageView
How to mock a custom ImageView for activity unit testing
我有一个 LoginActivity
,它在 onResume()
中加载了一个 SplashFragment
。
初始片段的布局 XML 包含一个名为 RotatingImageView
的自定义 ImageView
,顾名思义,它会在源图像附加到 Window.
现在,当我尝试使用 ActivityInstrumentationTestCase2<LoginActivity>
为 LoginActivity
编写单元测试时,这会导致问题。我正在尝试 运行 在真实设备(无根)而不是模拟器上进行测试。
getActivity()
调用启动了 activity 但由于旋转图像视图(顺便说一句,这是一个动画),espresso 卡住了。我知道浓缩咖啡不喜欢在那里播放动画。我得到
的例外情况
"espresso couldn't launch intent within 45 seconds. Perhaps the main
thread has not gone idle within a reasonable amount of time? There
could be an animation or something constantly repainting the screen.
Or the activity is doing network calls on creation? See the thread dump
logs. For your reference the last time the event queue was idle before
your activity launch request was 1487296262885 and now the last time
the queue went idle was: 1487296262885. If these numbers are the same
your activity might be hogging the event queue..."
现在显然问题是 stop/mock 动画。
我已经从设备 -> 设置 -> 开发人员选项中禁用了所有动画选项,但是当 activity 启动时我仍然看到图像在旋转,所以这没有帮助。
我也调查了 Disable animations for Espresso tests 但这对我也没有太大帮助。我可能做错了,但无论如何,它没有帮助。
另一种选择是使用特殊意图启动 LoginActivity
,它告诉 activity 这是正在测试中启动,因此当您加载片段时它会禁用动画。这种方法可行,但并不理想,因为它涉及在主要 class 中添加代码,这纯粹是为了测试。
另一个解决方案可能是模拟 RotatingImageView
并在开始加载之前将其注入 SplashFragment
。我会模拟对 startSpinningAnimation
的调用,所以当它加载到 Window 时它不会启动动画。
我的问题是:这可能吗?我可以在对 getActivity()
的调用完成之前以某种方式模拟并将此自定义 imageView
注入到我的片段中吗?
是的,有可能,您可以创建一个名为 AnimationUtil
的 class,将您的动画方法放入其中 class 并在测试期间模拟它们。
public Animation getWhateverAnimation(int duration){
RotateAnimation anim = new RotateAnimation(0f, 350f, 15f, 15f);
anim.setInterpolator(new LinearInterpolator());
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(duration);
return anim;
}
并在您的 androidTest
包(不是 main
包)中创建 MockAnimationUtil
extend
AnimationUtil
并覆盖和方法。
public Animation getWhateverAnimation(int duration){
return super.getWhateverAnimation(0);
}
我有一个 LoginActivity
,它在 onResume()
中加载了一个 SplashFragment
。
初始片段的布局 XML 包含一个名为 RotatingImageView
的自定义 ImageView
,顾名思义,它会在源图像附加到 Window.
现在,当我尝试使用 ActivityInstrumentationTestCase2<LoginActivity>
为 LoginActivity
编写单元测试时,这会导致问题。我正在尝试 运行 在真实设备(无根)而不是模拟器上进行测试。
getActivity()
调用启动了 activity 但由于旋转图像视图(顺便说一句,这是一个动画),espresso 卡住了。我知道浓缩咖啡不喜欢在那里播放动画。我得到
"espresso couldn't launch intent within 45 seconds. Perhaps the main thread has not gone idle within a reasonable amount of time? There could be an animation or something constantly repainting the screen. Or the activity is doing network calls on creation? See the thread dump logs. For your reference the last time the event queue was idle before your activity launch request was 1487296262885 and now the last time the queue went idle was: 1487296262885. If these numbers are the same your activity might be hogging the event queue..."
现在显然问题是 stop/mock 动画。
我已经从设备 -> 设置 -> 开发人员选项中禁用了所有动画选项,但是当 activity 启动时我仍然看到图像在旋转,所以这没有帮助。
我也调查了 Disable animations for Espresso tests 但这对我也没有太大帮助。我可能做错了,但无论如何,它没有帮助。
另一种选择是使用特殊意图启动
LoginActivity
,它告诉 activity 这是正在测试中启动,因此当您加载片段时它会禁用动画。这种方法可行,但并不理想,因为它涉及在主要 class 中添加代码,这纯粹是为了测试。
另一个解决方案可能是模拟 RotatingImageView
并在开始加载之前将其注入 SplashFragment
。我会模拟对 startSpinningAnimation
的调用,所以当它加载到 Window 时它不会启动动画。
我的问题是:这可能吗?我可以在对 getActivity()
的调用完成之前以某种方式模拟并将此自定义 imageView
注入到我的片段中吗?
是的,有可能,您可以创建一个名为 AnimationUtil
的 class,将您的动画方法放入其中 class 并在测试期间模拟它们。
public Animation getWhateverAnimation(int duration){
RotateAnimation anim = new RotateAnimation(0f, 350f, 15f, 15f);
anim.setInterpolator(new LinearInterpolator());
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(duration);
return anim;
}
并在您的 androidTest
包(不是 main
包)中创建 MockAnimationUtil
extend
AnimationUtil
并覆盖和方法。
public Animation getWhateverAnimation(int duration){
return super.getWhateverAnimation(0);
}