I am trying to calculate distance between two locations, I tried both location.distanceTo and Location.distanceBetween method but in both cases 0 is returned, I am not sure what am I doing wrong. Here is my method:
public static double distance(double lat1, double lon1, double lat2, double lon2, DistanceUnit unit) {
Location location1 = new Location("");
location1.setLatitude(lat1);
location1.setLongitude(lon1);
Location location2 = new Location("");
location2.setLatitude(lat2);
location2.setLongitude(lon2);
// Distance in km
double dist = location1.distanceTo(location2) / 1000;
if (unit == DistanceUnit.Miles) {
// Distance in miles
dist = dist / 1.6;
}
return dist;
}
The unit test I am running to ensure that the test run is:
@Test
public void testDistance() {
double lat1 = 40.2582279;
double lon1 = -75.2654062;
double lat2 = 40.476492;
double lon2 = -75.355655;
double distance = LocationUtils.distance(lat1, lon1, lat2, lon2, DistanceUnit.Kilometer);
Assert.assertEquals(20, distance, 2);
}
And result I am getting is:
java.lang.AssertionError:
Expected :20.0
Actual :0.0
Thanks in advance
Have you tried using the LocationUtils.distance()
method in your app running on a phone/emulator? I would guess that it works as you'd expect in that situation.
When you run a unit test, it's being run on your computer, not on an Android device. You can't use the built-in Android classes (like Location). From the docs:
By default, the Android Plug-in for Gradle executes your local unit tests against a modified version of the android.jar library, which does not contain any actual code. Instead, method calls to Android classes from your unit test throw an exception. This is to make sure you test only your code and do not depend on any particular behavior of the Android platform (that you have not explicitly mocked).
It looks like you encountered this exception, which would have looked like this
java.lang.RuntimeException: Method setLatitude in android.location.Location not mocked. See http://g.co/androidstudio/not-mocked for details.
at android.location.Location.setLatitude(Location.java)
at example.com.stackoverflow.LocationUtils.distance(LocationUtils.java:13)
Did you then read this which told you that you could add
android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
to your build.gradle
file? This does prevent the android classes from throwing exceptions when you try to use them, but note that what this does is to
change the behavior so that methods instead return either null or zero
This is the exact behavior that you're seeing: location1.distanceTo(location2)
returns 0.
More generally, this particular unit test seems unnecessary; you're mostly testing the Android API instead of testing your own logic. Unless there's part of your code do you want to make sure is tested? That you keep the correct lat/longs together? That the unit conversion works as expected? Perhaps you could extract the logic for whatever piece you're worried about and unit test that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With