Wednesday, April 24, 2013

Android - Robolectric - Unit testing request location updates (LocationManager)

Here is the android code to register for network, GPS and passive location updates on activity create

Android Code to test :
public class MainActivity extends Activity implements LocationListener {
private Location latestLocation;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
initLocationListener();
}
private void initLocationListener() {
LocationManager locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
List<String> allProviders = locationManager.getAllProviders();
for (String provider : allProviders) {
locationManager.requestLocationUpdates(provider, 0, 0, this);
}
}
@Override
public void onLocationChanged(Location location) {
latestLocation = location;
}
public Location latestLocation() {
return latestLocation;
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {}
@Override
public void onProviderDisabled(String s) {}
@Override
public void onProviderEnabled(String s) {}
}

To test the above code,
1) First you need to create a mock location
2) Get the ShadowLocationManager using the robolectric's shadowOf method
3) This shadow Object has a method called 'simulateLocation' to mock a location update.
4) Now we can assert the actual value obtained by the listener with the expected value

Robolectric Test :
@RunWith(RobolectricTestRunner.class)
public class MainActivityTest {
private MainActivity mainActivity;
@Before
public void setUp() {
mainActivity = new MainActivity();
mainActivity.onCreate(null);
}
@Test
public void shouldReturnTheLatestLocation() {
LocationManager locationManager = (LocationManager)
Robolectric.application.getSystemService(Context.LOCATION_SERVICE);
ShadowLocationManager shadowLocationManager = shadowOf(locationManager);
Location expectedLocation = location(NETWORK_PROVIDER, 12.0, 20.0);
shadowLocationManager.simulateLocation(expectedLocation);
Location actualLocation = mainActivity.latestLocation();
assertEquals(expectedLocation, actualLocation);
}
private Location location(String provider, double latitude, double longitude) {
Location location = new Location(provider);
location.setLatitude(latitude);
location.setLongitude(longitude);
location.setTime(System.currentTimeMillis());
return location;
}
}

2 comments:

  1. Useful stuff, only I had trouble calling the onCreate the way you do. This is another way:

    mainActivity = Robolectric.buildActivity(MainActivity.class).create().get();

    ReplyDelete