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
相关产品推荐
相关产品推荐

