Android ServiceTestCase for IntentService

走远了吗. 提交于 2019-11-29 09:25:41

问题


I'm currently writing unit tests for an android application and stumbled into the following issue:

I use the ServiceTestCase to test an IntentService like this:

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

public void testService()
{
    Intent intent = new Intent(getSystemContext(), MyIntentService.class);
    super.startService(intent);     
    assertNotNull(getService());        
}

However I noticed that my IntentService is created (means that onCreate is called) but I never receive a call into onHandleIntent(Intent intent)

Has anyone already tested an IntentService with the ServiceTestCase class?

Thanks!


回答1:


I just got started into testing my own IntentService and it's proving to be a bit of a headache.

Still trying to work things out but for the scenario where it seems that you do not receive a call to your method onHandleIntent(), (I'm not very good with the technicalities behind junit so forgive my use of terminology) it should be because the test framework, based on your code, actually tears down or end the test method once your call to startService returns. There is insufficient time for onHandleIntent to be triggered.

I verified the above theory by adding an infinite loop within my test case - only then can I see my log statements in onHandleIntent logged.




回答2:


This is a bit late, but I just struggled with this. You could solve this by creating a class that simply overrides the onStart of you service so it calls onHandleIntent directly. So for instance, if you have a LocationUpdaterService, you could create a fake class that overrides the onStart function like this:

public class LocationUpdaterServiceFake extends LocationUpdaterService {

@Override
public void onStart(Intent intent, int startId) {
    onHandleIntent(intent);
    stopSelf(startId);
}

LocationUpdaterService is a subclass of IntentService, so when you write your tests, just use the LocationUpdaterServiceFake class like this

public class LocationUpdateServiceTest extends ServiceTestCase<LocationUpdaterServiceFake> {

public LocationUpdateServiceTest()
{
    super(LocationUpdaterServiceFake.class);
}

public void testNewAreaNullLocation()
{
    Intent intent = new Intent();
    intent.setAction(LocationUpdaterService.ACTION_NEW_AREA);

    startService(intent);
}

}

Now whenever you call startService, it will bypass the threading code in IntentService and just call your onHandleIntent function




回答3:


You just have to add a:

Thread.sleep(XXXXXXX); 

Choose the XXXX after the startService, then it will let the thread go into the onHandleIntent method.




回答4:


In Android Studio 1.1, when running tests using the Run/Debug Configuration | Android Tests facility on any unit under test code (UUT) that extends IntentService, the ServiceTestCase.java (JUnit?) code does not call onHandleIntent(Intent intent) method in the UUT. ServiceTestCase only calls onCreate so the problem is in the test code.

protected void startService(Intent intent) {
    if (!mServiceAttached) {
        setupService();
    }
    assertNotNull(mService);

    if (!mServiceCreated) {
        mService.onCreate();
        mServiceCreated = true;
    }
    mService.onStartCommand(intent, 0, mServiceId);

    mServiceStarted = true;
}

In my file smSimulatorTest.java:

public class smSimulatorTest extends ServiceTestCase<smSimulator> 

At this point, I'm looking for other solutions in the testing framework that test UUTs through Intents since this is how IntentService is instantiated.

http://developer.android.com/reference/android/app/IntentService.html - To use it, extend IntentService and implement onHandleIntent(Intent). IntentService will receive the Intents, launch a worker thread, and stop the service as appropriate.

I, like others, put my code in the onHandleintent() as directed by the above documentation, however, ServiceTestCase only tests onStart and onStartCommand has shown above.




回答5:


This is my approach for now:

  1. The start Intent that invokes the service specifies the Service method to test

    
    public void test_can_do_the_work() {
        Intent startIntent = new Intent();
        startIntent.putExtra("IN_TEST_MODE", "TEST_SPECIFIC_METHOD");
        startIntent.setClass(getContext(), MyServiceToTest.class);
        startService(startIntent);
        assertNotNull(getService()); // Your assertion Service specific assertion
    }
    
  2. In the service onStart, we check for the specific Extra passed and call the method to test. This won't execute when Handle intent fired.

    
    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        String in_test_mode = intent.getStringExtra("TEST_SPECIFIC_METHOD");
        if(in_test_mode != null){
            doServiceWork();
        }
    }
    


来源:https://stackoverflow.com/questions/6667087/android-servicetestcase-for-intentservice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!