David
David

Reputation: 101

How to use an android dependency in unit tests?

I'm currently trying out TDD, but cannot get my head around how to use android dependencys in my unit tests.

I want to parse the JSON response of the PONS API to an Object. To test my Jsonparser, I tried to create a mock a spy, or just to a normal instance of the JsonReader the android.utils.JsonReader, which i then pass to my parser.


@Mock
private var reader : JsonReader = JsonReader(BufferedReader(FileReader(fileName)))


@Before
fun setUp(){
    MockitoAnnotations.initMocks(this)
}

@Test
fun parseTest() {

    val response = ResponseParser.parse(reader)

    val entry : response.Entry = response.getEntry(0)

    assertThat(entry.strings_displayed[0].get(0).first, `is`("Haus (Wohnhaus, Heim)"))
    assertThat(entry.strings_displayed[0].get(0).second, `is`("casa"))
    }

however none of my attempts has yielded the desired output. As of now i'm not able to use the JsonReader class. All i get is this error message (which of cause has been googled)

java.lang.RuntimeException: Method beginObject in android.util.JsonReader not mocked. See http://g.co/androidstudio/not-mocked for details.
at android.util.JsonReader.beginObject(JsonReader.java)
at com.huckebrink.remindyct.Data.PONSRequestParser$Companion.readJsonString(PONSRequestParser.kt:23)
at com.huckebrink.remindyct.Data.PONSRequestParser$Companion.parse(PONSRequestParser.kt:13)
at com.huckebrink.remindyct.ParsingUnitTest.parseTest(ParsingUnitTest.kt:47)
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.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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.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)

Upvotes: 1

Views: 1480

Answers (1)

Max Cruz
Max Cruz

Reputation: 1375

Well, my recommendation is to try to keep your Unit Test level without depending on the Android Framework, it makes everything easy if you can test only with Kotlin pure at Unit level and leave more complex tests for the Integration level.

Sometimes it's not so easy if the app is coupled, so, you can use some library as Robolectric to have the Android Framework working partially in your Unit Tests.

Search for: "Robolectric unit tests" to get examples. Good luck

UPDATE:

From the Android documentation https://developer.android.com/training/testing/unit-testing

Local tests: Unit tests that run on your local machine only. These tests are compiled to run locally on the Java Virtual Machine (JVM) to minimize execution time. If your tests depend on objects in the Android framework, we recommend using Robolectric. For tests that depend on your own dependencies, use mock objects to emulate your dependencies' behavior.

UPDATE 2:

JSON parsing should be part of the instrumented/integration level of tests, anyway, if you want the dependencies to use JsonParing on test directory you can add:

testCompile ‘org.json:json:20140107’

Upvotes: 1

Related Questions