Hello,
Is there a way to get either the Android's context or resources to use for a unit test? The use case is, having a json file we can reference vs hard coding the json string into the class we are unit testing.
Hello,
with Junit and Mockito we can't recreate a "real" Android context. You can use more easily make such thing in Android instrumented tests.
I can be interesting to investigate with new nitrogen project, or more about Robolectric project if we can do something.
If I were to use Robolectric, I know they offer a way to grab the context, how can I pass it to one of my modules?
If you want to add/override the existing definition of Application, you just have to provide a module like:
val androidContextModule = applicationContext{
bean { /* your instance of Application */ } bind Context::class
}
And then use the androidContextModule in the list of modules that you use, at the end of the list of modules: startKoin(listOf(module1, ..., androidContextModule))
Do we have a direct function to create an Android context with Robotlectric?
Hello @arnaudgiuliani, Below is a sample unit test using what you suggested and having success on accessing the resources! Please let me know if there is anything else I can do to help.
//Make sure you add this in your gradle inside android {}
testOptions {
unitTests.includeAndroidResources true
}
@RunWith(RobolectricTestRunner::class)
class ContextTest : KoinTest {
class ContextService(private val context: Context) {
fun getString(stringID: Int): String = context.getString(stringID)
}
val contextService: ContextService by inject()
@Before
fun setUp() {
val contextModule = applicationContext {
bean { RuntimeEnvironment.application } bind Context::class
factory { ContextService(get()) }
}
StandAloneContext.startKoin(listOf(contextModule))
}
@After
fun tearDown() {
StandAloneContext.closeKoin()
}
@Test
fun `testing if we have access to context`() {
Assert.assertEquals("context text", contextService.getString(R.string.context_text))
}
}
Great 馃憤
A sample/geetting started project will gather test samples for Android. I keep you in touch!
Unfortunately, I still have a problem with configuring robolectric and koin. I'm getting the following error
org.koin.error.AlreadyStartedException: Koin is already started. Run startKoin only once or use loadKoinModules
at org.koin.standalone.StandAloneContext.startKoin(StandAloneContext.kt:124)
at org.koin.standalone.StandAloneContext.startKoin$default(StandAloneContext.kt:121)
at org.koin.sampleapp.ContextTest.setUp(ContextTest.kt:33)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:253)
at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:130)
at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:42)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:84)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
I've also copy and paste @jmiecz code and tried on @arnaudgiuliani koin's sample app with the same results.
In the end it works. I use version 1.0.0-beta-6
My code:
@RunWith(RobolectricTestRunner::class)
class MyViewModelTest : AutoCloseKoinTest() {
val context: Context by inject()
val repository = mock<CountryRepository>()
val vm = MyViewModel(context, repository)
@Test
fun testA() {
...
}
@Test
fun testB() {
...
}
I don't have any @Before and @After nor specific modules for tests. Is my configuration alright or it works by accident? :)
Nop. For an instrumented test, your Koin container is already started via your startKoin().
What do you mean by instrumented tests @arnaudgiuliani ?
My tests are under test folder and run on jvm. Are they still called instrumented because of Robolectric
Yes kindof. This is unit test, with Android instrumented classes.
If you want to add/override the existing definition of
Application, you just have to provide a module like:val androidContextModule = applicationContext{ bean { /* your instance of Application */ } bind Context::class }And then use the
androidContextModulein the list of modules that you use, at the end of the list of modules:startKoin(listOf(module1, ..., androidContextModule))Do we have a direct function to create an Android context with Robotlectric?
where to put it?
Most helpful comment
Hello @arnaudgiuliani, Below is a sample unit test using what you suggested and having success on accessing the resources! Please let me know if there is anything else I can do to help.