Android FragmentScenario必须在FragmentInteractionListener上实现
我目前正在尝试使用本教程中建议的androidTest、mokito和espresso来测试android导航: 但我系统地得到了以下错误: E/MonitoringInstr:线程[main,5,main]遇到异常。将线程状态转储到输出,并锁定峡湾。 java.lang.RuntimeException:androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity@fa3e8be必须实现OnFragmentInteractionListener 以下是测试类:Android FragmentScenario必须在FragmentInteractionListener上实现,android,android-testing,instrumented-test,Android,Android Testing,Instrumented Test,我目前正在尝试使用本教程中建议的androidTest、mokito和espresso来测试android导航: 但我系统地得到了以下错误: E/MonitoringInstr:线程[main,5,main]遇到异常。将线程状态转储到输出,并锁定峡湾。 java.lang.RuntimeException:androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity@fa3e8be必须实现OnFragmentIntera
package developer.android.com.enlightme
import androidx.fragment.app.testing.launchFragmentInContainer
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.filters.MediumTest
import androidx.test.runner.AndroidJUnit4
import org.junit.Assert.*
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.*
@MediumTest
@RunWith(AndroidJUnit4::class)
class MainFragmentTest{
@Test
fun createDebateTransition(){
// Create a mock NavController
val mockNavController = mock(NavController::class.java)
// Create a graphical FragmentScenario for the TitleScreen
var mainScenario = launchFragmentInContainer<MainFragment>()
// Set the NavController property on the fragment
mainScenario.onFragment { fragment -> Navigation.setViewNavController(fragment.requireView(), mockNavController)
}
// Verify that performing a click "créer" prompt the correct Navigation action
onView(ViewMatchers.withId(R.id.nav_button_creer)).perform(ViewActions.click())
verify(mockNavController).navigate(R.id.action_mainFragment_to_create1Fragment)
}
}
}
以及模块graddle文件:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'maven'
apply plugin: 'kotlin-android-extensions'
apply plugin: "androidx.navigation.safeargs"
apply plugin: "kotlinx-serialization"
android {
compileSdkVersion 28
dataBinding {
enabled = true
}
defaultConfig {
applicationId "developer.android.com.enlightme"
minSdkVersion 18
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
android.defaultConfig.vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildToolsVersion = '28.0.3'
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.2.0-alpha01'
implementation 'androidx.core:core-ktx:1.2.0-rc01'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
//ViewModel
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-rc03'
//MaterialIO
implementation 'com.google.android.material:material:1.2.0-alpha03'
// Navigation
// Java
implementation "androidx.navigation:navigation-fragment:$navigationVersion"
implementation "androidx.navigation:navigation-ui:$navigationVersion"
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
//P2P with Nearby
implementation "com.google.android.gms:play-services-nearby:17.0.0"
//Serialization
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.13.0" // JVM dependency
//Testing
// Required -- JUnit 4 framework
testImplementation 'junit:junit:4.13-rc-2'
// Optional -- Robolectric environment
testImplementation 'androidx.test:core:1.2.0'
// Optional -- Mockito framework
//testImplementation 'org.mockito:mockito-core:1.10.19'
//androidTestImplementation "org.mockito:mockito-core:${var}"
//espresso
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
//androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion"
debugImplementation "androidx.fragment:fragment-testing:$fragmentVersion"
androidTestImplementation "org.mockito:mockito-core:${var}"
androidTestImplementation "com.google.dexmaker:dexmaker:1.2"
androidTestImplementation "com.google.dexmaker:dexmaker-mockito:1.2"
}
ext {
espressoVersion = '3.3.0-alpha03'
coroutinesVersion = '1.2.1'
fragmentVersion = '1.1.0'
var = '1.10.19'
var1 = '1.3.60'
kotlin_version = '1.3.60'
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
kotlin_version = '1.3.40'
navigationVersion = '2.2.0-rc04'
}
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
//navigation
def nav_version = "2.1.0-alpha05"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
以及项目梯度文件:
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'maven'
apply plugin: 'kotlin-android-extensions'
apply plugin: "androidx.navigation.safeargs"
apply plugin: "kotlinx-serialization"
android {
compileSdkVersion 28
dataBinding {
enabled = true
}
defaultConfig {
applicationId "developer.android.com.enlightme"
minSdkVersion 18
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
android.defaultConfig.vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildToolsVersion = '28.0.3'
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.2.0-alpha01'
implementation 'androidx.core:core-ktx:1.2.0-rc01'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
//ViewModel
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-rc03'
//MaterialIO
implementation 'com.google.android.material:material:1.2.0-alpha03'
// Navigation
// Java
implementation "androidx.navigation:navigation-fragment:$navigationVersion"
implementation "androidx.navigation:navigation-ui:$navigationVersion"
// Kotlin
implementation "androidx.navigation:navigation-fragment-ktx:$navigationVersion"
implementation "androidx.navigation:navigation-ui-ktx:$navigationVersion"
//P2P with Nearby
implementation "com.google.android.gms:play-services-nearby:17.0.0"
//Serialization
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.13.0" // JVM dependency
//Testing
// Required -- JUnit 4 framework
testImplementation 'junit:junit:4.13-rc-2'
// Optional -- Robolectric environment
testImplementation 'androidx.test:core:1.2.0'
// Optional -- Mockito framework
//testImplementation 'org.mockito:mockito-core:1.10.19'
//androidTestImplementation "org.mockito:mockito-core:${var}"
//espresso
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
//androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion"
debugImplementation "androidx.fragment:fragment-testing:$fragmentVersion"
androidTestImplementation "org.mockito:mockito-core:${var}"
androidTestImplementation "com.google.dexmaker:dexmaker:1.2"
androidTestImplementation "com.google.dexmaker:dexmaker-mockito:1.2"
}
ext {
espressoVersion = '3.3.0-alpha03'
coroutinesVersion = '1.2.1'
fragmentVersion = '1.1.0'
var = '1.10.19'
var1 = '1.3.60'
kotlin_version = '1.3.60'
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
kotlin_version = '1.3.40'
navigationVersion = '2.2.0-rc04'
}
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
//navigation
def nav_version = "2.1.0-alpha05"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version"
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
我正在使用Android studio 3.5.3
所以基本上,当我在手机上运行应用程序时,一切都很好,包括导航。问题源于仪器化测试本身。据我所知,FragmentScenario并没有实现OnFragmentInteractionListener。当然,我不能改变零碎的场景类,我不知道这件事应该如何处理。我是否使用了错误的工具来测试片段交互
谢谢大家! FragmentScenario获取您的片段并在容器中启动它,使用默认的空活动作为主机。它不会启动您的活动。目标是单独测试片段 当然,空主机活动不会实现OnFragmentInteractionListener,因为它是您创建的接口。在onAttach回调中,您强制主机活动实现此接口,并告诉它以其他方式抛出异常。这就是你在测试中遇到的错误 您可以删除onAttach方法中的else部分,错误将消失。但是您的侦听器将为null,并且依赖它的一些功能将无法正常工作
也许你也可以考虑改变这个体系结构。您可以考虑使用共享视图模型吗?这比与听众互动容易。如果您不想更改当前状态,可能您可以继续进行集成测试,而不是单独的片段测试
目前,我发现的唯一解决办法是完全避免类与OnFragmentInteractionListener接口。。。这是有限的。谢谢(有点晚了,抱歉…)你的见解。我最好改变我的架构:)