如果没有按钮,Espresso 不会记录任何意图
Espresso does no record any intent if there are no buttons
我正在尝试编写一个测试来验证使用浓缩咖啡启动的意图,问题是 intended() 没有记录任何意图。
我有这个测试
@Test
public void shoulddosomething(){
startActivity();
intended(hasComponent(hasClassName(TemplatePictureCaptureActivity.class.getName())));
}
在我的 activity 中我有这个代码
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(onRequestLayout());
Intent intent = new Intent(this, TemplatePictureCaptureActivity.class);
startActivity(intent);
}
测试结果是这样的
android.support.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: Wanted to match 1 intents. Actually matched 0 intents.
IntentMatcher: has component: has component with: class name: is "cat.helm.recertel.ui.templatepicturecapture.TemplatePictureCaptureActivity" package name: an instance of java.lang.String short class name: an instance of java.lang.String
Matched intents:[]
Recorded intents:[]
我已经尝试在 onClickListen 中启动意图并且它起作用了,但是没有它我无法让它起作用。我也尝试过使用闲置资源但没有运气。你知道如何实现吗?
稍等一下再尝试
intended(hasComponent(hasClassName(TemplatePictureCaptureActivity.class.getName())));
解决方法是注册一个空闲资源等待第二个activity。
在我的例子中,测试将保持如下:
@Test
public void shoulddosomething() {
startActivity();
String templatePictureActivityClassName = TemplatePictureCaptureActivity.class.getName();
Espresso.registerIdlingResources(new WaitActivityIsResumedIdlingResource(templatePictureActivityClassName));
intended(hasComponent(hasClassName(templatePictureActivityClassName)));
}
这里是闲置资源。
private static class WaitActivityIsResumedIdlingResource implements IdlingResource {
private final ActivityLifecycleMonitor instance;
private final String activityToWaitClassName;
private volatile ResourceCallback resourceCallback;
boolean resumed = false;
public WaitActivityIsResumedIdlingResource(String activityToWaitClassName) {
instance = ActivityLifecycleMonitorRegistry.getInstance();
this.activityToWaitClassName = activityToWaitClassName;
}
@Override
public String getName() {
return this.getClass().getName();
}
@Override
public boolean isIdleNow() {
resumed = isActivityLaunched();
if(resumed && resourceCallback != null) {
resourceCallback.onTransitionToIdle();
}
return resumed;
}
private boolean isActivityLaunched() {
Collection<Activity> activitiesInStage = instance.getActivitiesInStage(Stage.RESUMED);
for (Activity activity : activitiesInStage) {
if(activity.getClass().getName().equals(activityToWaitClassName)){
return true;
}
}
return false;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
this.resourceCallback = resourceCallback;
}
}
这可能与 Intents 组件初始化的竞争条件有关,而不是 startActivity
调用和 intended
的使用之间的竞争条件。如果您从 SUT activity onCreate
或 onResume
方法开始您的 activity,您应该查看以下测试规则。
我创建了一个 IntentsTestRule 来解决这个问题。 https://gist.github.com/pedrovgs/6a305ba4c5e3acfac854ce4c36558d9b
package com.aplazame.utils
import android.app.Activity
import androidx.test.espresso.intent.Intents
import androidx.test.rule.ActivityTestRule
class ExhaustiveIntentsTestRule<T : Activity> : ActivityTestRule<T> {
private var isInitialized: Boolean = false
constructor(activityClass: Class<T>) : super(activityClass)
constructor(activityClass: Class<T>, initialTouchMode: Boolean) : super(activityClass, initialTouchMode)
constructor(activityClass: Class<T>, initialTouchMode: Boolean, launchActivity: Boolean) : super(
activityClass,
initialTouchMode,
launchActivity
)
override fun beforeActivityLaunched() {
super.beforeActivityLaunched()
Intents.init()
isInitialized = true
}
override fun afterActivityFinished() {
super.afterActivityFinished()
if (isInitialized) {
// Otherwise will throw a NPE if Intents.init() wasn't called.
Intents.release()
isInitialized = false
}
}
}
与 AndroidX 中实现的原始 IntentsTestRule 的主要区别在于 Intents.init() 初始化。此时间在启动 SUT activity 之前调用。请记住,此测试规则还将记录用于启动 SUT activity.
的意图
我正在尝试编写一个测试来验证使用浓缩咖啡启动的意图,问题是 intended() 没有记录任何意图。
我有这个测试
@Test
public void shoulddosomething(){
startActivity();
intended(hasComponent(hasClassName(TemplatePictureCaptureActivity.class.getName())));
}
在我的 activity 中我有这个代码
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(onRequestLayout());
Intent intent = new Intent(this, TemplatePictureCaptureActivity.class);
startActivity(intent);
}
测试结果是这样的
android.support.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: Wanted to match 1 intents. Actually matched 0 intents.
IntentMatcher: has component: has component with: class name: is "cat.helm.recertel.ui.templatepicturecapture.TemplatePictureCaptureActivity" package name: an instance of java.lang.String short class name: an instance of java.lang.String
Matched intents:[]
Recorded intents:[]
我已经尝试在 onClickListen 中启动意图并且它起作用了,但是没有它我无法让它起作用。我也尝试过使用闲置资源但没有运气。你知道如何实现吗?
稍等一下再尝试
intended(hasComponent(hasClassName(TemplatePictureCaptureActivity.class.getName())));
解决方法是注册一个空闲资源等待第二个activity。
在我的例子中,测试将保持如下:
@Test
public void shoulddosomething() {
startActivity();
String templatePictureActivityClassName = TemplatePictureCaptureActivity.class.getName();
Espresso.registerIdlingResources(new WaitActivityIsResumedIdlingResource(templatePictureActivityClassName));
intended(hasComponent(hasClassName(templatePictureActivityClassName)));
}
这里是闲置资源。
private static class WaitActivityIsResumedIdlingResource implements IdlingResource {
private final ActivityLifecycleMonitor instance;
private final String activityToWaitClassName;
private volatile ResourceCallback resourceCallback;
boolean resumed = false;
public WaitActivityIsResumedIdlingResource(String activityToWaitClassName) {
instance = ActivityLifecycleMonitorRegistry.getInstance();
this.activityToWaitClassName = activityToWaitClassName;
}
@Override
public String getName() {
return this.getClass().getName();
}
@Override
public boolean isIdleNow() {
resumed = isActivityLaunched();
if(resumed && resourceCallback != null) {
resourceCallback.onTransitionToIdle();
}
return resumed;
}
private boolean isActivityLaunched() {
Collection<Activity> activitiesInStage = instance.getActivitiesInStage(Stage.RESUMED);
for (Activity activity : activitiesInStage) {
if(activity.getClass().getName().equals(activityToWaitClassName)){
return true;
}
}
return false;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
this.resourceCallback = resourceCallback;
}
}
这可能与 Intents 组件初始化的竞争条件有关,而不是 startActivity
调用和 intended
的使用之间的竞争条件。如果您从 SUT activity onCreate
或 onResume
方法开始您的 activity,您应该查看以下测试规则。
我创建了一个 IntentsTestRule 来解决这个问题。 https://gist.github.com/pedrovgs/6a305ba4c5e3acfac854ce4c36558d9b
package com.aplazame.utils
import android.app.Activity
import androidx.test.espresso.intent.Intents
import androidx.test.rule.ActivityTestRule
class ExhaustiveIntentsTestRule<T : Activity> : ActivityTestRule<T> {
private var isInitialized: Boolean = false
constructor(activityClass: Class<T>) : super(activityClass)
constructor(activityClass: Class<T>, initialTouchMode: Boolean) : super(activityClass, initialTouchMode)
constructor(activityClass: Class<T>, initialTouchMode: Boolean, launchActivity: Boolean) : super(
activityClass,
initialTouchMode,
launchActivity
)
override fun beforeActivityLaunched() {
super.beforeActivityLaunched()
Intents.init()
isInitialized = true
}
override fun afterActivityFinished() {
super.afterActivityFinished()
if (isInitialized) {
// Otherwise will throw a NPE if Intents.init() wasn't called.
Intents.release()
isInitialized = false
}
}
}
与 AndroidX 中实现的原始 IntentsTestRule 的主要区别在于 Intents.init() 初始化。此时间在启动 SUT activity 之前调用。请记住,此测试规则还将记录用于启动 SUT activity.
的意图