user3200382
user3200382

Reputation: 143

Android Unit Testing / Mockito: android.location.Location not mocked

I am trying to learn basic JUnit and Mockito testing on Android. I'm trying to write unit tests for a simple class that handles finding the user's location from Location Services on behalf of activities that need location information.

I have been trying to create "faked location" to test with:

@Test
public void testLocationReceived() throws Exception {
    Location fakeLocation = new Location(LocationManager.NETWORK_PROVIDER);
    fakeLocation.setLongitude(100);
    fakeLocation.setLatitude(-80);
    ...  
}

But I get the error:

java.lang.RuntimeException: Method setLongitude in android.location.Location not mocked.

I understand that unit tests on Android run on the JVM, so you don't have access to anything that requires the operating system / framework, but is this one of those cases as well?

Upvotes: 10

Views: 7915

Answers (3)

Justin Brown
Justin Brown

Reputation: 91

Using the Robolectric test runner solved this for me.

@RunWith(RobolectricTestRunner::class)
class TestClass {
   ...
}

Note: I did not need

testOptions {
        unitTests.returnDefaultValues = true
}

Don't forget to add the necessary Robolectric dependencies if you don't already have it in your project.

Upvotes: 2

I had the same pb as you. @John Huang answer helped me. You first need to mock the location then use mockito when to put the values that you wanted .here is my code

@RunWith(PowerMockRunner::class)
class MapExtensionTest {
 @Mock
    private lateinit var location: Location

    //region calculateDistance
    @Test
    fun `given a valid store and a valid location  to calculateDistance should return the correct distance`() {
        Mockito.`when`(store.coordinate).thenReturn(coordinate)
        Mockito.`when`(coordinate.latitude).thenReturn(FAKE_LAT)
        Mockito.`when`(coordinate.longitude).thenReturn(FAKE_LON)
        Mockito.`when`(location.latitude).thenReturn(FAKE_LAT1)
        Mockito.`when`(location.longitude).thenReturn(FAKE_LON1)
        val result = FloatArray(1)
        Location.distanceBetween(
            store.coordinate.latitude,
            store.coordinate.longitude,
            location.latitude, location.longitude, result
        )

        store.calculateDistance(location)

        Assert.assertTrue(store.distance == result[0].toDouble())
    }

Dont forget this like john said

testOptions {
    unitTests.returnDefaultValues = true
}

If you have pb with import here is my test dependency but i dont remember witch one is important for this example so keep in mind that you may not need all

//testing dependencies
testImplementation "junit:junit:$junitVersion"
testImplementation "org.mockito:mockito-inline:${mockitoInlineVersion}"
testImplementation "androidx.arch.core:core-testing:${coreTestingVersion}"
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:${mockitoKotlinVersion}"
androidTestImplementation "org.mockito:mockito-android:${mockitoAndroidVersion}"
testImplementation group: 'org.powermock', name: 'powermock-api-mockito2', version: "${powerMockMockitoVersion}"
testImplementation group: 'org.powermock', name: 'powermock-module-junit4', version: "${powerMockjUnitVersion}"

Upvotes: 4

John Huang
John Huang

Reputation: 1338

You should add the following in build.gradle (app):

testOptions {
        unitTests.returnDefaultValues = true
}

More detail: http://tools.android.com/tech-docs/unit-testing-support#TOC-Method-...-not-mocked.-

Upvotes: 5

Related Questions