I'm trying to run a local unit test that depends on the context, and was following this guide: https://developer.android.com/training/testing/unit-testing/local-unit-tests#kotlin and I set up my project like this (following this link : https://developer.android.com/training/testing/set-up-project ):
build.gradle(app)
android {
compileSdkVersion 28
buildToolsVersion '27.0.3'
defaultConfig {
minSdkVersion 21
targetSdkVersion 27
versionCode 76
versionName "2.6.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
useLibrary 'android.test.runner'
useLibrary 'android.test.base'
useLibrary 'android.test.mock'
}
testOptions {
unitTests.returnDefaultValues = true
unitTests.all {
// All the usual Gradle options.
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
outputs.upToDateWhen { false }
showStandardStreams = true
}
}
unitTests.includeAndroidResources = true
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
androidTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion", {
exclude group: 'com.android.support', module: 'support-annotations'
})
// Espresso UI Testing dependencies
implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion"
testImplementation 'androidx.test:core:1.0.0'
// AndroidJUnitRunner and JUnit Rules
androidTestImplementation 'androidx.test:runner:1.1.0'
androidTestImplementation 'androidx.test:rules:1.1.0'
// Espresso Assertions
androidTestImplementation 'androidx.test.ext:junit:1.0.0'
androidTestImplementation 'androidx.test.ext:truth:1.0.0'
androidTestImplementation 'com.google.truth:truth:0.42'
implementation 'androidx.multidex:multidex:2.0.0'
}
My espresso_version is espressoVersion = '3.1.0'
My test that is located in module-name/src/test/java/ looks like this:
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.instacart.library.truetime.TrueTime
import edu.mira.aula.shared.extensions.android.trueDateNow
import edu.mira.aula.shared.network.ConnectivityHelper
import kotlinx.coroutines.experimental.runBlocking
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import java.util.*
import java.util.concurrent.CountDownLatch
class TimeExtensionsUnitTest {
private lateinit var instrumentationCtx: Context
@Before
fun setup() {
instrumentationCtx = ApplicationProvider.getApplicationContext<Context>()
}
@Test
fun testTrueTimeValueReturnsIfInitialized() {
if (ConnectivityHelper.isOnline(instrumentationCtx)) {
runBlocking {
val countDownLatch = CountDownLatch(1)
TrueTime.build()
.withSharedPreferencesCache(instrumentationCtx)
.withConnectionTimeout(10000)
.initialize()
countDownLatch.countDown()
try {
countDownLatch.await()
val dateFromTrueTime = trueDateNow()
val normalDate = Date()
Assert.assertNotEquals(dateFromTrueTime, normalDate)
} catch (e: InterruptedException) {
}
}
}
}
Everytime I run it, it gives me:
java.lang.IllegalStateException: No instrumentation registered! Must run under a registering instrumentation.
at androidx.test.platform.app.InstrumentationRegistry.getInstrumentation(InstrumentationRegistry.java:45)
at androidx.test.core.app.ApplicationProvider.getApplicationContext(ApplicationProvider.java:41)
If I run it as a Instrumental Test(changing the package) it runs without errors.
But I thought that this guide was exactly to be able to run unit test using Android Framework classes such as Context.
I even tried run that class UnitTestSample
but the same error occurs.
I also removed all android.support dependencies from my project
Any ideas on how to solve it?
Update
You should no longer encounter this error if youre using the latest gradle version.
I also encountered this issue.
If you look at migrating to Robolectric 4.0 here, it suggest to add the following line in your gradle.properties
.
android.enableUnitTestBinaryResources=true
The problem is that, if you add this you your gradle.properties
, it will output this warning:
WARNING: The option setting 'android.enableUnitTestBinaryResources=true' is experimental and unsupported.
Now, if you look at Robolectric releases here. You could see that this is a known issue where they state that
Android Gradle Plugin may report the following warning, which may be safely ignored: WARNING: The option setting 'android.enableUnitTestBinaryResources=true' is experimental and unsupported.. Android Gradle Plugin 3.4 will resolve this issue.
I believe unless you could update you gradle to 3.4. You won't be able to solve this issue.
What I did instead was to include Robolectric 4.0 as dependency.
testImplementation "org.robolectric:robolectric:4.0.2"
and annotate my test class with
@RunWith(RobolectricTestRunner::class)
This should make your test work.
Now when you run the test, you'll notice that Robolectric will log the following:
[Robolectric] NOTICE: legacy resources mode is deprecated; see http://robolectric.org/migrating/#migrating-to-40
Ignore this for now but as soon as you could update your gradle, migrate to the new Robolectric testing.