Reputation: 1312
I am receiving the following error when attempting to use a FragmentScenario in an instrumented test. I believe the issue to be related to the build type as tests are ran under "staging" instead of "debug" build config.
Any help would be greatly appreciated.
Error
java.lang.RuntimeException: Unable to resolve activity for: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example/androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity (has extras) }
at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:387)
at androidx.test.core.app.InstrumentationActivityInvoker.startActivity(InstrumentationActivityInvoker.java:416)
at androidx.test.core.app.ActivityScenario.launchInternal(ActivityScenario.java:265)
at androidx.test.core.app.ActivityScenario.launch(ActivityScenario.java:226)
at androidx.fragment.app.testing.FragmentScenario.internalLaunch(FragmentScenario.java:299)
at androidx.fragment.app.testing.FragmentScenario.launchInContainer(FragmentScenario.java:282)
at com.example.view.fragments.MainFragmentTest.testNavigation(MainFragmentTest.kt:139)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:549)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:154)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:395)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)
The test being ran which is a spitting image of the docs from google on testing navigation https://developer.android.com/guide/navigation/navigation-testing#kotlin
@Test
fun testNavigation() {
// Create a TestNavHostController
val navController = TestNavHostController(ApplicationProvider.getApplicationContext())
navController.setGraph(R.navigation.nav_graph)
// Create a graphical FragmentScenario for the TitleScreen
// Without adding androidTestImplementation "...fragment-testing" to the build gradle this errors and cannot build. This is because we are in staging variant instead of debug variant.
val fragmentScenario = launchFragmentInContainer<MainFragment>()
// Set the NavController property on the fragment
fragmentScenario.onFragment { fragment ->
Navigation.setViewNavController(fragment.requireView(), navController)
}
// Verify that performing a click changes the NavController’s state
onView(withId(R.id.login)).perform(click())
assertThat(navController.currentDestination?.id.toString(), equalTo(R.id.dashboardFragment.toString()))
}
Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example">
....
<application
android:name=".Example"
android:allowBackup="true"
android:fullBackupContent="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="${cleartextTrafficPermitted}">
<activity
android:name="com.example.controllers.LauncherActivity"
android:screenOrientation="portrait"
android:theme="@style/AppTheme.Launcher"
tools:ignore="LockedOrientationActivity"
android:windowSoftInputMode="stateHidden|adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.controllers.MainActivity"
android:screenOrientation="portrait"
android:windowSoftInputMode="stateHidden|adjustResize"
android:theme="@style/AppTheme.Launcher"
tools:ignore="LockedOrientationActivity" />
...
</application>
</manifest>
build.gradle(app)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.google.gms.google-services'
apply plugin: "androidx.navigation.safeargs.kotlin"
ext.okhttp_version = '4.7.2'
ext.retrofit_version = '2.9.0'
ext.mockito_version = '3.3.3'
ext.coroutine_version = '1.3.9'
ext.test_version = '1.3.0'
ext.fragment_version = '1.2.5'
ext.nav_version = '2.3.0'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
testBuildType "staging"
defaultConfig {
applicationId "com.example"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
buildTypes {
debug {
buildConfigField "String", "API_DOMAIN", '"https://testing.com"'
// This is needed when API's are connecting to HTTP endpoints. Primary purpose is
// for the staging buildType to use a non-SSL mock server locally.
manifestPlaceholders.cleartextTrafficPermitted ="true"
}
staging {
initWith(buildTypes.debug)
buildConfigField "String", "API_DOMAIN", '"http://127.0.0.1/"'
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
buildConfigField "String", "API_DOMAIN", '"https://production.com"'
// Production version will not need to access HTTP endpoints. Disable
// because it poses a security risk.
manifestPlaceholders.cleartextTrafficPermitted ="false"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
viewBinding {
enabled = true
}
kotlinOptions {
jvmTarget = "1.8"
}
testOptions {
unitTests.includeAndroidResources = true
unitTests.returnDefaultValues = true
execution 'ANDROIDX_TEST_ORCHESTRATOR'
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
...
// Test dependencies
testImplementation 'junit:junit:4.13'
testImplementation "org.mockito:mockito-inline:$mockito_version"
testImplementation "org.mockito:mockito-core:$mockito_version"
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation "org.mockito:mockito-android:$mockito_version"
androidTestImplementation "androidx.test:core:$test_version"
androidTestImplementation "androidx.test:rules:$test_version"
androidTestImplementation "androidx.test:runner:$test_version"
androidTestImplementation "com.squareup.okhttp3:mockwebserver:$okhttp_version"
androidTestUtil "androidx.test:orchestrator:$test_version"
// Without this, if I change the active build variant to staging I cannot use FragmentScenario as the IDE returns "unresolved reference"
androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version"
// This is the correct implementation of fragment-testing
debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
androidTestImplementation('com.android.support.test.espresso:espresso-contrib:3.0.2') {
// Necessary to avoid version conflicts
exclude group: 'com.android.support', module: 'appcompat'
exclude group: 'com.android.support', module: 'support-v4'
exclude group: 'com.android.support', module: 'support-annotations'
exclude module: 'recyclerview-v7'
}
// Testing Navigation
androidTestImplementation "androidx.navigation:navigation-testing:$nav_version"
...
}
UPDATE
If I remove both androidTestImplementation and debugImplementation and replace with stagingImplementation so that the lib is available to staging build variant this causes all test classes to fail with "no tests found"
// androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version"
// debugImplementation "androidx.fragment:fragment-testing:$fragment_version"
//noinspection FragmentGradleConfiguration
stagingImplementation "androidx.fragment:fragment-testing:$fragment_version"
Upvotes: 0
Views: 4240
Reputation: 684
For my case, I was using
debugImplementation "androidx.fragment:fragment-testing:1.5.0"
and I downgraded it to
debugImplementation "androidx.fragment:fragment-testing:1.3.0-alpha08"
This solved my issue hope it helps
Upvotes: 3
Reputation: 200010
If you are not running your tests against debug
builds, then debugImplementation
is not enough. You need to add:
stagingImplementation "androidx.fragment:fragment-testing:$fragment_version"
Upvotes: 5