Welcome to JiKe DevOps Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
223 views
in Technique[技术] by (71.8m points)

java - Android Instrumented Test - Mocking Location doesn't work (returns null although testLocation is set)

My application works perfectly but now I have to test a class which gets the Location via the LocationManager so I decided to activate Mock Location in the Manifest:

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"
    tools:ignore="ProtectedPermissions" />

and I also activated Mock Location on the Emulator (Dev Settings). This is my method which uses the LocationManager:

public Location getCurrentLocation() {
    try {
        LocationManager locationManager = (LocationManager) ctx.getSystemService(Context.LOCATION_SERVICE);
        if (ActivityCompat.checkSelfPermission(ctx, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        return locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    } catch (NullPointerException e) {
        return null;
    }
}

And this is my test class:

public class LocationTest {

Context context;
@Rule
public GrantPermissionRule permissionRule = GrantPermissionRule.grant(Manifest.permission.ACCESS_FINE_LOCATION);

@Before
public void init() {
    context = InstrumentationRegistry.getInstrumentation().getTargetContext();

    Location mockLocation = new Location(android.location.LocationManager.GPS_PROVIDER);
    android.location.LocationManager locationManager = (android.location.LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    locationManager.addTestProvider(android.location.LocationManager.GPS_PROVIDER, false, false,
            false, false, true, true, true, 0, 5);
    locationManager.setTestProviderEnabled(android.location.LocationManager.GPS_PROVIDER, true);

    mockLocation.setLatitude(-20.000);
    mockLocation.setLongitude(10.000);
    mockLocation.setAltitude(10);
    mockLocation.setBearing(0);
    mockLocation.setAccuracy(5);
    mockLocation.setSpeed(0);
    mockLocation.setTime(System.currentTimeMillis());
    mockLocation.setElapsedRealtimeNanos(System.nanoTime());

    locationManager.setTestProviderStatus(android.location.LocationManager.GPS_PROVIDER, LocationProvider.AVAILABLE, null, System.currentTimeMillis());
    locationManager.setTestProviderLocation(android.location.LocationManager.GPS_PROVIDER, mockLocation);
}

@After
public void tearDown() {
    android.location.LocationManager locationManager = (android.location.LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    locationManager.removeTestProvider(android.location.LocationManager.GPS_PROVIDER);
}

@Test
public void getCurrentLocationTest() {
    LocationClass locClass = new LocationClass(context);
    Location loc = locClass.getCurrentLocation();
    assertFalse(loc == null);
}

}

For some reason, "return locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);" in getCurrentLocation() returns null always (no Exception thrown, and Permissions are granted).

When I start my app it works but when I try to mock the Location in the tests or even try it without mocking the Location, no Location is found by the LocationManager (Activating Mock Location works though -> No Exceptions thrown, just the Manager won't detect any Location).

Can I even Mock the Location for an Instrumented Test and return it with getLastKnownLocation? What could I try to make it work?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

Please log in or register to answer this question.

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to JiKe DevOps Community for programmer and developer-Open, Learning and Share
...