ServiceTestCasepublic 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.IBinder | bindService(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.
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.Application | getApplication()Return the Application object being used by the Service under test.
return mApplication;
| public T | getService()
return mService;
| public android.content.Context | getSystemContext()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 mSystemContext;
| public void | setApplication(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.
mApplication = application;
| protected void | setUp()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 void | setupService()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 void | shutdownService()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 void | startService(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}.
assertFalse(mServiceStarted);
assertFalse(mServiceBound);
if (!mServiceAttached) {
setupService();
}
assertNotNull(mService);
if (!mServiceCreated) {
mService.onCreate();
mServiceCreated = true;
}
mService.onStart(intent, mServiceId);
mServiceStarted = true;
| protected void | tearDown()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.
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 void | testServiceTestCaseSetUpProperly()
setupService();
assertNotNull("service should be launched successfully", mService);
|
|