FileDocCategorySizeDatePackage
ServiceTestCase.javaAPI DocAndroid 1.5 API10664Wed May 06 22:42:02 BST 2009android.test

ServiceTestCase

public abstract class ServiceTestCase extends AndroidTestCase
This test case provides a framework in which you can test Service classes in a controlled environment. It provides basic support for the lifecycle of a Service, and hooks by which you can inject various dependencies and control the environment in which your Service is tested.

Lifecycle Support. Every Service is designed to be accessed within a specific sequence of calls. . In order to support the lifecycle of a Service, this test case will make the following calls at the following times.

  • The test case will not call onCreate() until your test calls {@link #startService} or {@link #bindService}. This gives you a chance to set up or adjust any additional framework or test logic before onCreate().
  • When your test calls {@link #startService} or {@link #bindService} the test case will call onCreate(), and then call the corresponding entry point in your service. It will record any parameters or other support values necessary to support the lifecycle.
  • After your test completes, the test case {@link #tearDown} function is automatically called, and it will stop and destroy your service with the appropriate calls (depending on how your test invoked the service.)

Dependency Injection. Every service has two inherent dependencies, the {@link android.content.Context Context} in which it runs, and the {@link android.app.Application Application} with which it is associated. This framework allows you to inject modified, mock, or isolated replacements for these dependencies, and thus perform a true unit test.

If simply run your tests as-is, your Service will be injected with a fully-functional Context, and a generic {@link android.test.mock.MockApplication MockApplication} object. You can create and inject alternatives to either of these by calling {@link AndroidTestCase#setContext(Context) setContext()} or {@link #setApplication setApplication()}. You must do this before calling startService() or bindService(). The test framework provides a number of alternatives for Context, including {link android.test.mock.MockContext MockContext}, {@link android.test.RenamingDelegatingContext RenamingDelegatingContext}, and {@link android.content.ContextWrapper ContextWrapper}.

Fields Summary
Class
mServiceClass
private android.content.Context
mSystemContext
private android.app.Application
mApplication
private T
mService
private boolean
mServiceAttached
private boolean
mServiceCreated
private boolean
mServiceStarted
private boolean
mServiceBound
private android.content.Intent
mServiceIntent
private int
mServiceId
Constructors Summary
public ServiceTestCase(Class serviceClass)

        mServiceClass = serviceClass;
    
Methods Summary
protected android.os.IBinderbindService(android.content.Intent intent)
Start the service under test, in the same way as if it was started by {@link android.content.Context#bindService Context.bindService()}, providing the arguments it supplied. Return the communication channel to the service. May return null if clients can not bind to the service. The returned {@link android.os.IBinder} is usually for a complex interface that has been described using aidl. Note: In order to test with this interface, your service must implement a getService() method, as shown in samples.ApiDemos.app.LocalService.

param
intent The Intent as if supplied to {@link android.content.Context#bindService}.
return
Return an IBinder for making further calls into the Service.

        assertFalse(mServiceStarted);
        assertFalse(mServiceBound);
        
        if (!mServiceAttached) {
            setupService();
        }
        assertNotNull(mService);
        
        if (!mServiceCreated) {
            mService.onCreate();
            mServiceCreated = true;
        }
        // no extras are expected by unbind
        mServiceIntent = intent.cloneFilter();
        IBinder result = mService.onBind(intent);
        
        mServiceBound = true;
        return result;
    
public android.app.ApplicationgetApplication()
Return the Application object being used by the Service under test.

return
Returns the application object.
see
#setApplication

        return mApplication;
    
public TgetService()

return
Returns the actual service under test.


                
       
        return mService;
    
public android.content.ContextgetSystemContext()
Return a real (not mocked or instrumented) system Context that can be used when generating Mock or other Context objects for your Service under test.

return
Returns a reference to a normal Context.

        return mSystemContext;
    
public voidsetApplication(android.app.Application application)
Set the application for use during the test. If your test does not call this function, a new {@link android.test.mock.MockApplication MockApplication} object will be generated.

param
application The Application object that will be injected into the Service under test.

        mApplication = application;
    
protected voidsetUp()
This will do the work to instantiate the Service under test. After this, your test code must also start and stop the service.

        super.setUp();
        
        // get the real context, before the individual tests have a chance to muck with it
        mSystemContext = getContext();

    
protected voidsetupService()
Create the service under test and attach all injected dependencies (Context, Application) to it. This will be called automatically by {@link #startService} or by {@link #bindService}. If you wish to call {@link AndroidTestCase#setContext(Context) setContext()} or {@link #setApplication setApplication()}, you must do so before calling this function.

        mService = null;
        try {
            mService = mServiceClass.newInstance();
        } catch (Exception e) {
            assertNotNull(mService);
        }
        if (getApplication() == null) {
            setApplication(new MockApplication());
        }
        mService.attach(
                getContext(),
                null,               // ActivityThread not actually used in Service
                mServiceClass.getName(),
                null,               // token not needed when not talking with the activity manager
                getApplication(),
                null                // mocked services don't talk with the activity manager
                );
        
        assertNotNull(mService);
        
        mServiceId = new Random().nextInt();
        mServiceAttached = true;
    
protected voidshutdownService()
This will make the necessary calls to stop (or unbind) the Service under test, and call onDestroy(). Ordinarily this will be called automatically (by {@link #tearDown}, but you can call it directly from your test in order to check for proper shutdown behaviors.

        if (mServiceStarted) {
            mService.stopSelf();
            mServiceStarted = false;
        } else if (mServiceBound) {
            mService.onUnbind(mServiceIntent);
            mServiceBound = false;
        }
        if (mServiceCreated) {
            mService.onDestroy();
        }
    
protected voidstartService(android.content.Intent intent)
Start the service under test, in the same way as if it was started by {@link android.content.Context#startService Context.startService()}, providing the arguments it supplied. If you use this method to start the service, it will automatically be stopped by {@link #tearDown}.

param
intent The Intent as if supplied to {@link android.content.Context#startService}.

        assertFalse(mServiceStarted);
        assertFalse(mServiceBound);
        
        if (!mServiceAttached) {
            setupService();
        }
        assertNotNull(mService);
        
        if (!mServiceCreated) {
            mService.onCreate();
            mServiceCreated = true;
        }
        mService.onStart(intent, mServiceId);
        
        mServiceStarted = true;
    
protected voidtearDown()
Shuts down the Service under test. Also makes sure all resources are cleaned up and garbage collected before moving on to the next test. Subclasses that override this method should make sure they call super.tearDown() at the end of the overriding method.

throws
Exception

        shutdownService();
        mService = null;

        // Scrub out members - protects against memory leaks in the case where someone 
        // creates a non-static inner class (thus referencing the test case) and gives it to
        // someone else to hold onto
        scrubClass(ServiceTestCase.class);

        super.tearDown();
    
public voidtestServiceTestCaseSetUpProperly()

        setupService();
        assertNotNull("service should be launched successfully", mService);