测试模拟位置不起作用

时间:2012-03-13 12:55:58

标签: android unit-testing location

I have written a simple Gps Service. Now I am writing a testcase for testing it. I am trying to send a mock location but the onLocation changed is not getting called in my GpsService location listener.

Here is my GpsService








/**
* returns the binder object that client of this can bind to
*/
@Override
public IBinder onBind(Intent arg0) {

    return mBinder;
}

@Override
public void onCreate() {
    super.onCreate();
    Log.e("GpsService","StartService");


}

private class MyLocationListener implements  LocationListener {

    @Override
    public void onLocationChanged(Location loc) {
        Log.e("GpsService","Location in GpsService"+loc.toString());
        if(loc.hasAccuracy() && loc.getAccuracy() <= minAccuracyMeters)
        {
            if(targetLocation != null)
            {
                float distance = loc.distanceTo(targetLocation);
                Log.e("GpsService ","Location latitude +"+loc.getLatitude()+"longitude "+loc.getLongitude());
                if(distance < 5.0)
                    Toast.makeText(getBaseContext(), "You have reached the target location", Toast.LENGTH_LONG).show();

            }
        }

    }

public void setTargetLocation (Location _location){
    targetLocation = _location;
}


/**
 * Class for clients to access. Because we know this service always runs in
 * the same process as its clients, we don't need to deal with IPC.
 */
public class LocalBinder extends Binder {
        GpsService getService() {
                return GpsService.this;
        }
}

private final IBinder mBinder = new LocalBinder();

@Override
public void onDestroy() {
    if(lm != null)
        lm.removeUpdates(locationListener);
    super.onDestroy();
}

//Setting up for test case
public void setUpProvider(String provider){

    lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

    locationListener = new MyLocationListener();

    lm.requestLocationUpdates(provider, 
                    minTimeMillis, 
                    minDistanceMeters,
                    locationListener);

}

Now here is my TestCase

公共类MockLocationTest扩展了ServiceTestCase {

private LocationManager locationManager = null;
private static final String MOCK_GPS_PROVIDER = "MOCK_GPS_PROVIDER";
private List<String> data = new ArrayList<String>();

public MockLocationTest(Class<GpsService> serviceClass) {
    super(serviceClass);

}

public MockLocationTest() {
    super(GpsService.class);

}


 @Override
    protected void setupService() {

        super.setupService();
        System.out.println("Service Set Up");
        Intent intent = new Intent(getContext(),GpsService.class);
        startService(intent);
        assertNotNull("The Service should not be null",getService());
        System.out.println("Service Started");
    }


    @Override
    protected void setUp() throws Exception {
        super.setUp();



    }



    @MediumTest
    public void testBindable() {

        Intent startIntent = new Intent();
        startIntent.setClass(getContext(), GpsService.class);
        IBinder service =  bindService(startIntent);
        assertNotNull("Bound to service ",service);
        getService().setUpProvider(MOCK_GPS_PROVIDER);

        Location demo = new Location(MOCK_GPS_PROVIDER);
        demo.setLatitude(22.579937);
        demo.setLongitude(88.486805);
        getService().setTargetLocation(demo);

        System.out.println("Test Bindable");
    }






    @SmallTest
    public void testMockData(){
        locationManager = (LocationManager) getContext().getSystemService((Context.LOCATION_SERVICE));

        locationManager.setTestProviderEnabled(MOCK_GPS_PROVIDER, true);
        Location location = new Location(MOCK_GPS_PROVIDER);
        location.setLatitude(22.579937);
        location.setLongitude(88.486805);

        location.setTime(System.currentTimeMillis());

        // show debug message in log


        // provide the new location

        locationManager.setTestProviderLocation(MOCK_GPS_PROVIDER, location);//send mock data


    }

    @Override
    protected void tearDown() throws Exception {

        super.tearDown();
    }

}

不幸的是,我无法在服务中的onLocationChange回调中看到任何日志。测试用例成功运行。  我在服务和测试服务的清单

中添加了以下内容
 <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>

Can anybody help me here

我也试过把它放在一个函数中

@LargeTest         public void testBindable(){

        Intent startIntent = new Intent();
        startIntent.setClass(getContext(), GpsService.class);
        IBinder service =  bindService(startIntent);
        assertNotNull("Bound to service ",service);
        LocationManager locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
        locationManager.addTestProvider(MOCK_GPS_PROVIDER, false, false,
                false, false, false, false, false, 0, 5);
        locationManager.setTestProviderEnabled(MOCK_GPS_PROVIDER, true);
        getService().setUpProvider(MOCK_GPS_PROVIDER,locationManager);


        Location demo = new Location(MOCK_GPS_PROVIDER);
        demo.setLatitude(22.579937);
        demo.setLongitude(88.486805);
        demo.setTime(System.currentTimeMillis());
        getService().setTargetLocation(demo);

        Location narkeldanga = new Location(MOCK_GPS_PROVIDER);
        narkeldanga.setLatitude(22.578986);
        narkeldanga.setLongitude(88.470154);
        narkeldanga.setTime(System.currentTimeMillis());



        locationManager.setTestProviderLocation(MOCK_GPS_PROVIDER, narkeldanga);

        try {
            Thread.sleep(10000);

            // gracefully handle Thread interruption (important!)
            if(Thread.currentThread().isInterrupted())
                throw new InterruptedException("");
        } catch (InterruptedException e) {

        }

        locationManager.setTestProviderLocation(MOCK_GPS_PROVIDER, demo);

        try {
            Thread.sleep(10000);

            // gracefully handle Thread interruption (important!)
            if(Thread.currentThread().isInterrupted())
                throw new InterruptedException("");
        } catch (InterruptedException e) {

        }

        System.out.println("Test Bindable");
    }

但无济于事。

2 个答案:

答案 0 :(得分:0)

这是我和其他人在jUnit测试中遇到的问题。也就是说,当您的服务在另一个线程中运行时,testBindable()将在一个线程中运行。结果是位置服务仍然在设置,甚至没有考虑在测试结束时使用你的回调,jUnit从内存中清除所有内容。我仍然在寻找一个很好的配方来构建这样的测试,但我可以提出一些你可以尝试的方法。最简单的方法是在测试中放入sleep(),以便在其他线程中处理时间。例如:

public void testBindable() throws Exception {

    Intent startIntent = new Intent();
    startIntent.setClass(getContext(), GpsService.class);
    IBinder service =  bindService(startIntent);
    assertNotNull("Bound to service ",service);
    getService().setUpProvider(MOCK_GPS_PROVIDER);

    Location demo = new Location(MOCK_GPS_PROVIDER);
    demo.setLatitude(22.579937);
    demo.setLongitude(88.486805);
    getService().setTargetLocation(demo);

    TimeUnit.SECONDS.sleep(5);

    System.out.println("Test Bindable");
}

出于多种原因,这种方法并不理想。 5秒(或任何你放入的东西)有时可能不够或在其他情况下时间太长。

或者,您可以使用锁存器或其他机制来检测回调何时执行。但是,这种方法使您的代码与使用仅仅由测试使用的锁存器(或者您可以使用互斥锁)相混淆,理想情况下不应该是测试中的实际应用程序的一部分。

答案 1 :(得分:0)