alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Android example source code file (ServiceTestCase.java)

This example Android source code file (ServiceTestCase.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Android by Example" TM.

Java - Android tags/keywords

activitythread, android, androidtestcase, app, application, class, content, context, exception, ibinder, intent, mockapplication, os, override, service, servicetestcase, test, util

The ServiceTestCase.java Android example source code

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.test;

import android.app.Application;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.test.mock.MockApplication;

import java.lang.reflect.Field;
import java.util.Random;

/**
 * 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.
 *
 * <p>Lifecycle Support.
 * Every Service is designed to be accessed within a specific sequence of
 * calls.  <insert link to Service lifecycle doc here>. 
 * In order to support the lifecycle of a Service, this test case will make the
 * following calls at the following times.
 *
 * <ul>
  • 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().</li> * <li>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.</li> * <li>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.)</li> * </ul> * * <p>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. * * <p>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 <i>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}. */ public abstract class ServiceTestCase<T extends Service> extends AndroidTestCase { Class<T> mServiceClass; private Context mSystemContext; private Application mApplication; public ServiceTestCase(Class<T> serviceClass) { mServiceClass = serviceClass; } private T mService; private boolean mServiceAttached = false; private boolean mServiceCreated = false; private boolean mServiceStarted = false; private boolean mServiceBound = false; private Intent mServiceIntent = null; private int mServiceId; /** * @return Returns the actual service under test. */ public T getService() { return mService; } /** * This will do the work to instantiate the Service under test. After this, your test * code must also start and stop the service. */ @Override protected void setUp() throws Exception { super.setUp(); // get the real context, before the individual tests have a chance to muck with it mSystemContext = getContext(); } /** * 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. */ protected void setupService() { 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; } /** * 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}. */ protected void startService(Intent intent) { assertFalse(mServiceStarted); assertFalse(mServiceBound); if (!mServiceAttached) { setupService(); } assertNotNull(mService); if (!mServiceCreated) { mService.onCreate(); mServiceCreated = true; } mService.onStart(intent, mServiceId); mServiceStarted = true; } /** * 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 <a href="{@docRoot}guide/developing/tools/aidl.html">described using * aidl</a>. * * 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. */ protected IBinder bindService(Intent intent) { 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; } /** * 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. */ protected void shutdownService() { if (mServiceStarted) { mService.stopSelf(); mServiceStarted = false; } else if (mServiceBound) { mService.onUnbind(mServiceIntent); mServiceBound = false; } if (mServiceCreated) { mService.onDestroy(); } } /** * 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 */ @Override protected void tearDown() 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(); } /** * 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. */ public void setApplication(Application application) { mApplication = application; } /** * Return the Application object being used by the Service under test. * * @return Returns the application object. * * @see #setApplication */ public Application getApplication() { return mApplication; } /** * 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. */ public Context getSystemContext() { return mSystemContext; } public void testServiceTestCaseSetUpProperly() throws Exception { setupService(); assertNotNull("service should be launched successfully", mService); } }
  • Other Android examples (source code examples)

    Here is a short list of links related to this Android ServiceTestCase.java source code file:

    ... this post is sponsored by my books ...

    #1 New Release!

    FP Best Seller

     

    new blog posts

     

    Copyright 1998-2021 Alvin Alexander, alvinalexander.com
    All Rights Reserved.

    A percentage of advertising revenue from
    pages under the /java/jwarehouse URI on this website is
    paid back to open source projects.