如何使用 Espresso intents 存根 select images intent?

How to stub select images intent using Espresso intents?

这是我第一次使用 espresso intents,我按照 android-testing 项目中提供的 IntentsBasicSamle,但没有解决。

在我的应用程序中,我有一个 activity,其中用户 select 的多个图像然后 returned 图像显示在 gridview 中,现在通过使用我想要的浓缩咖啡意图每次都模拟这个而不去实际的图像选择器和return一些指定的图像。

没有错误,但在我 运行 测试时仍然打开图像选择器 window。我觉得我做错了,但我不明白它是如何工作的。

我正在使用 apk 进行测试。

这是照片选择器的调用方式

应用代码

这就是我调用 select 图片的方式 Intent 和结果在 onActivityResult 中处理。

if (ApiUtils.checkApiLevel(18)) {
        //API18+
        intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    }
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent,      getActivity().getString(R.string.fragment_image_selection_select_picture)), 1);

测试代码

@RunWith(AndroidJUnit4.class)
@LargeTest
public class ImagesTests {

private static final String LAUNCHER_ACTIVITY_FULL_CLASSNAME = "com.company.recorder.RecorderActivity";
private static Class<? extends Activity> activityClass;
private ServiceValidatorIdlingResource serviceValidatorIdlingResource;

static {
    try {
        activityClass = (Class<? extends Activity>) Class.forName(LAUNCHER_ACTIVITY_FULL_CLASSNAME);
    } catch (ClassNotFoundException e) {
        throw new RuntimeException(e);
    }
}

/**
 * Change espresso default view idling time
 * so that test can wait for long time
 */
@Before
public void registerWaitService() {
    EspressoSolo.setIdlingResourceTimeout(30);

    Instrumentation.ActivityResult result = createImageCaptureActivityResultStub();

    // Stub the Intent.
    intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(result);

   //For API 18 and above
    intending(hasAction(Intent.EXTRA_ALLOW_MULTIPLE)).respondWith(result);

    //intending(not(isInternal())).respondWith(result);
}

private Instrumentation.ActivityResult createImageCaptureActivityResultStub() {
    // Put the drawable in a bundle.
    Bundle bundle = new Bundle();
    Uri imageUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
            InstrumentationRegistry.getTargetContext().getPackageName()+ '/' +
            InstrumentationRegistry.getTargetContext().getResources().getResourceTypeName(R.drawable.abc_ic_menu_copy_mtrl_am_alpha) + '/' +
            InstrumentationRegistry.getTargetContext().getResources().getResourceEntryName(R.drawable.abc_ic_menu_copy_mtrl_am_alpha) );

    Parcelable parcelable = (Parcelable)imageUri;

    ArrayList<Parcelable> parcels = new ArrayList<>();
    parcels.add(parcelable);

    bundle.putParcelableArrayList(Intent.EXTRA_STREAM, parcels);

    // Create the Intent that will include the bundle.
    Intent resultData = new Intent();
    resultData.putExtras(bundle);

    // Create the ActivityResult with the Intent.
    return new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData);
}

@Rule
public IntentsTestRule<?> mIntentsRule = new IntentsTestRule<>(
        activityClass);


/**
 * In this test images are taken during the recording
 * add the images taken during the recording through add photos card
 * displayed after recording is stopped.
 *
 * @throws Exception
 */
@Test
public void testAddImagesFromPhotosCard() throws Exception {

    onView(withId(Recorder.getId("recorderpage_record"))).perform(click());

    Log.d("called", "other package");
    IdlingResource idlingResource0 = new RecordingWaitIdlingResource(5000);
    Espresso.registerIdlingResources(idlingResource0);

    Log.d("called", "other package");
    onView(withId(Recorder.getId("card_topText"))).perform(click());
    Espresso.unregisterIdlingResources(idlingResource0);
    onView(withId(Recorder.getId("recorderpage_stop"))).perform(click());
    //Log.d("called", "other package");
    IdlingResource idlingResource2 = new RecordingWaitIdlingResource(2000);
    Espresso.registerIdlingResources(idlingResource2);
    onView(withId(Recorder.getId("recorderpage_statustext")))
            .perform(click());
    Espresso.unregisterIdlingResources(idlingResource2);

    onView(withId(Recorder.getId("pager"))).perform(swipeLeft());

    onData(allOf()).onChildView(withId(Recorder.getId("recordsOverflow"))).
            atPosition(0).perform(click());

    IdlingResource idlingResource3 = new RecordingWaitIdlingResource(2000);
    Espresso.registerIdlingResources(idlingResource3);
    onData(allOf()).onChildView(withId(Recorder.getId("recordsOverflow"))).
            atPosition(0).perform(click());
    Espresso.unregisterIdlingResources(idlingResource3);
    onView(withText("Add an image")).perform(click());

    Instrumentation.ActivityResult result = createImageCaptureActivityResultStub();
    intending(toPackage("com.android.documentsui")).respondWith(result);

     /* I actually dont know which preinstalled app is opened by intent, I saw this com.android.documentsui, also tried with photos and gallery package names */

    intending(toPackage("com.android.documentsui.DocumentsActivity")).respondWith(result);

    intending(hasAction(Intent.ACTION_GET_CONTENT)).respondWith(result);

    //Now click on add images
    onView(withId(Recorder.getId("menu_fragment_imagewizard_selection_add"))).perform(click());

    //Just waits for 2seconds
    IdlingResource idlingResource4 = new RecordingWaitIdlingResource(2000);
    Espresso.registerIdlingResources(idlingResource4);
    onView(withText("Add images")).perform(click());
    Espresso.unregisterIdlingResources(idlingResource4);

}
}

最后,这是对我有用的,发布我的答案

Bundle bundle = new Bundle();
    ArrayList<Parcelable> parcels = new ArrayList<>();
    Intent resultData = new Intent();
    Uri uri1 = Uri.parse("file://mnt/sdcard/img01.jpg");
    Parcelable parcelable1 = (Parcelable) uri1;
    parcels.add(parcelable1);
    bundle.putParcelableArrayList(Intent.EXTRA_STREAM, parcels);
    // Create the Intent that will include the bundle.
    resultData.putExtras(bundle);

    intending(not(isInternal())).respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData));

权限

 @Rule public GrantPermissionRule permissionRule = GrantPermissionRule.grant(android.Manifest.permission.YOUR_PERMISSION; 

它的工作试一试.. 在@Before 方法中

Intent resultData = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intending(not(isInternal())).respondWith(new Instrumentation.ActivityResult(Activity.RESULT_OK, resultData));

测试方法是:

onView(withId(R.id.imgSelect)).perform(click());
onView(withId(R.id.img1)).check(matches(CustomMatcher.hasDrawable()));