【问题标题】:Testing Mock Locations not Working测试模拟位置不起作用
【发布时间】:2012-03-13 12:55:57
【问题描述】:
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 回调中看不到任何日志。测试用例成功运行。 我在我的服务和 testservice 的清单中都添加了以下内容

 <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 公共无效 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");
    }

但无济于事。

【问题讨论】:

    标签: android unit-testing location


    【解决方案1】:

    这是我和其他人在 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 秒(或您输入的任何内容)有时可能不够,或者在其他情况下时间过多。

    或者,您可以使用闩锁或其他机制来检测您的回调何时执行。但是,这种方法会使您的代码与仅由测试使用的锁存器(或者您可以使用互斥锁)变得复杂,并且理想情况下不应成为实际测试应用程序的一部分。

    【讨论】:

      【解决方案2】:

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-01-07
        • 2016-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-01-05
        • 2014-11-14
        相关资源
        最近更新 更多