Reputation: 4692
When I try to start one of my junit
tests, all of them fail due to multiple errors. This is due to the fact, that my Application class
has some variables in it, which are initialized in the "normal" app start, but not when I start a test. Commenting the variables out might help, but that is an ugly solution, to always comment stuff out, when starting a test.
@HiltAndroidApp
@InternalCoroutinesApi
class App : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
@Inject lateinit var workerList: WorkerList
override fun onCreate() {
super.onCreate()
plantTimberTree()
enableOfflinePersistence()
workerList.startDownloadDocumentWork()
}
override fun getWorkManagerConfiguration(): Configuration =
Configuration.Builder().setWorkerFactory(workerFactory).build()
}
private fun plantTimberTree() = Timber.plant(Timber.DebugTree())
private fun enableOfflinePersistence() {
val settings = firestoreSettings { isPersistenceEnabled = true }
Firebase.firestore.firestoreSettings = settings
}
@RunWith(RobolectricTestRunner::class)
@Config(maxSdk = Build.VERSION_CODES.P, minSdk = Build.VERSION_CODES.P)
class EmailViewModelTest {
}
java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process null. Make sure to call FirebaseApp.initializeApp(Context) first.
at com.google.firebase.FirebaseApp.getInstance(FirebaseApp.java:184)
at com.google.firebase.firestore.FirebaseFirestore.getInstance(FirebaseFirestore.java:91)
at com.google.firebase.firestore.ktx.FirestoreKt.getFirestore(Firestore.kt:32)
at com.example.app.AppKt.enableOfflinePersistence(App.kt:44)
at com.example.app.AppKt.access$enableOfflinePersistence(App.kt:1)
at com.example.app.App.onCreate(App.kt:24)
at org.robolectric.android.internal.AndroidTestEnvironment.lambda$installAndCreateApplication$0(AndroidTestEnvironment.java:288)
at org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:75)
at org.robolectric.android.internal.AndroidTestEnvironment.installAndCreateApplication(AndroidTestEnvironment.java:288)
at org.robolectric.android.internal.AndroidTestEnvironment.setUpApplicationState(AndroidTestEnvironment.java:171)
at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:319)
at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:254)
at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
kotlin.UninitializedPropertyAccessException: lateinit property workerList has not been initialized
at com.example.app.App.onCreate(App.kt:25)
at org.robolectric.android.internal.AndroidTestEnvironment.lambda$installAndCreateApplication$0(AndroidTestEnvironment.java:288)
at org.robolectric.util.PerfStatsCollector.measure(PerfStatsCollector.java:75)
at org.robolectric.android.internal.AndroidTestEnvironment.installAndCreateApplication(AndroidTestEnvironment.java:288)
at org.robolectric.android.internal.AndroidTestEnvironment.setUpApplicationState(AndroidTestEnvironment.java:171)
at org.robolectric.RobolectricTestRunner.beforeTest(RobolectricTestRunner.java:319)
at org.robolectric.internal.SandboxTestRunner$2.lambda$evaluate$0(SandboxTestRunner.java:254)
at org.robolectric.internal.bytecode.Sandbox.lambda$runOnMainThread$0(Sandbox.java:89)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Is there a way to determine, whether a test has been started or not? How should I change my Application class in order to get my tests running again?
I appreciate every help, thank you.
Upvotes: 2
Views: 927
Reputation: 3472
I see you're using RobolectricTestRunner.
There's a couple different ways to solve the problem of FirebaseApp getting into weird states during a Robolectric test vs how it would behave if your Application class had been initialized normally.
(1) You can use Robolectric to specify a special test Application context to use that does whatever you want with Firebase.
(2) You can use Roboelectric to create a shadow class for FirebaseApp that behaves in whatever way you desire. (Here's one example in which I have the shadow class catch that exception you referenced and initialize Firebase.)
The advantage of writing a shadow class for FirebaseApp is that it can be configured to intervene for any way your code may access FirebaseApp, and a robolectric.properties file can configure your whole test package.
Upvotes: 1
Reputation: 23
This can be solved by implementing Roboelectric library as it provides the android environment to run your tests.
Check the below link to get detailed description how to use it. I found it very useful.
https://codelabs.developers.google.com/codelabs/advanced-android-kotlin-training-testing-basics/#0
Upvotes: 0