2012-03-13 75 views
0
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"); 
    } 

,但以下徒勞無功。

回答

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秒(或者你投入的任何東西)可能有時不夠或者其他情況下的時間太長。

或者,您可以使用鎖存器或其他機制來檢測回調執行的時間。然而,這種方法使用鎖存器(或者你可以使用互斥鎖)使你的代碼複雜化,這些鎖只能被測試使用,理想情況下不應該成爲被測實際應用程序的一部分。

+0

試過(檢查代碼改性問題)沒有效果:( – windwaker 2012-03-17 05:25:50