You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android测试中SearchView无法展开及输入失败问题求助

无法在Espresso测试中展开SearchView并执行输入操作

问题详情

尝试对折叠状态的SearchView执行点击展开并输入文本的Espresso测试时,click()操作无法展开搜索栏,导致后续typeText()执行失败,报错提示目标View不满足输入约束(has-input-connection=false)。

测试代码

@Test
fun searchFriends_displaysFilteredResults() {
    // Launch the FriendsFragment.
    launchFragmentInContainer<FriendsFragment>(themeResId = R.style.Theme_Bootcamp)

    var searchText = "John Doe"
    Thread.sleep(1000)
    onView(withId(R.id.friends_search_bar)).perform(click())
    onView(withId(R.id.friends_search_bar))
        .perform(typeText("John Doe"), closeSoftKeyboard())

    // Check if the filtered result is displayed.
    onView(withText("John Doe")).check(matches(isDisplayed()))
}

布局XML代码

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/fragment_friends"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.SearchView
        android:id="@+id/friends_search_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Search for users..."
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/friends_list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/friends_search_bar"
        app:layout_constraintBottom_toBottomOf="parent"
        tools:listitem="@layout/item_friend" />
</androidx.constraintlayout.widget.ConstraintLayout>

报错信息

androidx.test.espresso.PerformException: Error performing 'type text(John Doe)' on view 'view.getId() is <2131230996/com.epfl.drawyourpath:id/friends_search_bar>'.
Caused by: java.lang.RuntimeException: Action will not be performed because the target view does not match one or more of the following constraints:
(((view has effective visibility  and view.getGlobalVisibleRect() to return non-empty rectangle)) and (view.onCreateInputConnection() is not null or is assignable from class ))
Target view: "SearchView{id=2131230996, res-name=friends_search_bar, visibility=VISIBLE, width=1080, height=126, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, layout-params=androidx.constraintlayout.widget.ConstraintLayout$LayoutParams@YYYYYY, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}"

解决方案

1. 直接操作SearchView内部的EditText

SearchView是复合控件,折叠状态下输入区域不可交互,直接点击整个View无法触发展开。可以定位到其内部的EditText控件进行操作:

@Test
fun searchFriends_displaysFilteredResults() {
    launchFragmentInContainer<FriendsFragment>(themeResId = R.style.Theme_Bootcamp)

    // 定位SearchView内部的EditText并执行操作
    onView(allOf(isDescendantOfA(withId(R.id.friends_search_bar)), instanceOf(EditText::class.java)))
        .perform(click(), typeText("John Doe"), closeSoftKeyboard())

    onView(withText("John Doe")).check(matches(isDisplayed()))
}

2. 自定义ViewAction强制展开SearchView

通过调用SearchView的isIconified = false方法直接展开搜索栏,再执行输入操作:

// 自定义展开SearchView的ViewAction
fun expandSearchView(): ViewAction {
    return object : ViewAction {
        override fun getConstraints(): Matcher<View> {
            return isAssignableFrom(SearchView::class.java)
        }

        override fun getDescription(): String {
            return "Expand search view"
        }

        override fun perform(uiController: UiController, view: View) {
            (view as SearchView).isIconified = false
        }
    }
}

// 在测试中使用
@Test
fun searchFriends_displaysFilteredResults() {
    launchFragmentInContainer<FriendsFragment>(themeResId = R.style.Theme_Bootcamp)

    // 先展开SearchView
    onView(withId(R.id.friends_search_bar)).perform(expandSearchView())
    // 再操作内部EditText输入文本
    onView(allOf(isDescendantOfA(withId(R.id.friends_search_bar)), instanceOf(EditText::class.java)))
        .perform(typeText("John Doe"), closeSoftKeyboard())

    onView(withText("John Doe")).check(matches(isDisplayed()))
}

3. 优化测试等待逻辑

移除Thread.sleep(1000),改用Espresso的等待逻辑确保View完全加载,避免因初始化未完成导致的点击无效:

// 等待SearchView可用后再操作
onView(withId(R.id.friends_search_bar)).perform(waitUntil { it.isEnabled })

问题原因

  • SearchView默认折叠状态下,内部EditText处于不可交互状态,直接对整个SearchView执行typeText()会因无输入连接(has-input-connection=false)失败。
  • 直接点击整个SearchView可能未命中负责展开的图标区域,无法触发展开逻辑。

内容的提问来源于stack exchange,提问作者Kristian Safta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 20:43:19