如果没有按钮,Espresso不会记录任何意图

Bor*_*rja 12 testing android android-intent android-espresso

我正在尝试编写一个测试来验证使用espresso启动意图,问题是目标()没有记录任何意图.

我有这个测试

  @Test
public void shoulddosomething(){
    startActivity();
    intended(hasComponent(hasClassName(TemplatePictureCaptureActivity.class.getName())));

}
Run Code Online (Sandbox Code Playgroud)

在我的活动中我有这个代码

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(onRequestLayout());
    Intent intent = new Intent(this, TemplatePictureCaptureActivity.class);
    startActivity(intent);
}
Run Code Online (Sandbox Code Playgroud)

测试结果是这样的.

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:[]
Run Code Online (Sandbox Code Playgroud)

我试图在onClickListen中启动意图并且它有效,但没有它我无法让它工作.我也尝试过闲置的资源而没有运气.你知道如何实现这个目标吗?

Bor*_*rja 12

解决方案是注册一个空闲资源以等待第二个活动.

在我的情况下,测试将保持如下:

  @Test
public void shoulddosomething() {
    startActivity();
    String templatePictureActivityClassName = TemplatePictureCaptureActivity.class.getName();
    Espresso.registerIdlingResources(new WaitActivityIsResumedIdlingResource(templatePictureActivityClassName));
    intended(hasComponent(hasClassName(templatePictureActivityClassName)));
}
Run Code Online (Sandbox Code Playgroud)

这里是闲置的资源.

 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您可以考虑在测试后取消注册空闲资源. (3认同)

小智 3

这可能与 Intents 组件初始化上的竞争条件有关,而不是与 的startActivity调用和使用之间的竞争条件有关intended。如果您从 SUT 活动onCreateonResume方法开始活动,您应该查看以下测试规则。

我创建了一个 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
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

与 AndroidX 中实现的原始 IntentsTestRule 的主要区别在于 Intents.init() 初始化。该时间在启动 SUT 活动之前调用。请记住,此测试规则还将记录用于启动 SUT 活动的意图。