| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 1 | page.title=Service Testing |
| 2 | parent.title=Testing |
| 3 | parent.link=index.html |
| 4 | @jd:body |
| 5 | |
| 6 | <div id="qv-wrapper"> |
| 7 | <div id="qv"> |
| 8 | <h2>In this document</h2> |
| 9 | <ol> |
| 10 | <li> |
| 11 | <a href="#DesignAndTest">Service Design and Testing</a> |
| 12 | </li> |
| 13 | <li> |
| 14 | <a href="#ServiceTestCase">ServiceTestCase</a> |
| 15 | </li> |
| 16 | <li> |
| 17 | <a href="#MockObjects">Mock object classes</a> |
| 18 | </li> |
| 19 | <li> |
| 20 | <a href="#TestAreas">What to Test</a> |
| 21 | </li> |
| 22 | </ol> |
| 23 | <h2>Key Classes</h2> |
| 24 | <ol> |
| 25 | <li>{@link android.test.InstrumentationTestRunner}</li> |
| 26 | <li>{@link android.test.ServiceTestCase}</li> |
| 27 | <li>{@link android.test.mock.MockApplication}</li> |
| 28 | <li>{@link android.test.RenamingDelegatingContext}</li> |
| 29 | </ol> |
| 30 | <h2>Related Tutorials</h2> |
| 31 | <ol> |
| 32 | <li> |
| 33 | <a href="{@docRoot}tools/testing/activity_test.html">Activity Testing Tutorial</a> |
| 34 | </li> |
| 35 | </ol> |
| 36 | <h2>See Also</h2> |
| 37 | <ol> |
| 38 | <li> |
| 39 | <a href="{@docRoot}tools/testing/testing_eclipse.html"> |
| 40 | Testing From Eclipse with ADT</a> |
| 41 | </li> |
| 42 | <li> |
| 43 | <a href="{@docRoot}tools/testing/testing_otheride.html"> |
| 44 | Testing From Other IDEs</a> |
| 45 | </li> |
| 46 | </ol> |
| 47 | </div> |
| 48 | </div> |
| 49 | <p> |
| 50 | Android provides a testing framework for Service objects that can run them in |
| 51 | isolation and provides mock objects. The test case class for Service objects is |
| 52 | {@link android.test.ServiceTestCase}. Since the Service class assumes that it is separate |
| 53 | from its clients, you can test a Service object without using instrumentation. |
| 54 | </p> |
| 55 | <p> |
| 56 | This document describes techniques for testing Service objects. If you aren't familiar with the |
| 57 | Service class, please read the <a href="{@docRoot}guide/components/services.html"> |
| 58 | Services</a> document. If you aren't familiar with Android testing, please read |
| 59 | <a href="{@docRoot}tools/testing/testing_android.html">Testing Fundamentals</a>, |
| 60 | the introduction to the Android testing and instrumentation framework. |
| 61 | </p> |
| 62 | <h2 id="DesignAndTest">Service Design and Testing</h2> |
| 63 | <p> |
| 64 | When you design a Service, you should consider how your tests can examine the various states |
| 65 | of the Service lifecycle. If the lifecycle methods that start up your Service, such as |
| 66 | {@link android.app.Service#onCreate() onCreate()} or |
| 67 | {@link android.app.Service#onStartCommand(Intent, int, int) onStartCommand()} do not normally |
| 68 | set a global variable to indicate that they were successful, you may want to provide such a |
| 69 | variable for testing purposes. |
| 70 | </p> |
| 71 | <p> |
| 72 | Most other testing is facilitated by the methods in the {@link android.test.ServiceTestCase} |
| 73 | test case class. For example, the {@link android.test.ServiceTestCase#getService()} method |
| 74 | returns a handle to the Service under test, which you can test to confirm that the Service is |
| 75 | running even at the end of your tests. |
| 76 | </p> |
| 77 | <h2 id="ServiceTestCase">ServiceTestCase</h2> |
| 78 | <p> |
| 79 | {@link android.test.ServiceTestCase} extends the JUnit {@link junit.framework.TestCase} class |
| 80 | with with methods for testing application permissions and for controlling the application and |
| 81 | Service under test. It also provides mock application and Context objects that isolate your |
| 82 | test from the rest of the system. |
| 83 | </p> |
| 84 | <p> |
| 85 | {@link android.test.ServiceTestCase} defers initialization of the test environment until you |
| 86 | call {@link android.test.ServiceTestCase#startService(Intent) ServiceTestCase.startService()} or |
| 87 | {@link android.test.ServiceTestCase#bindService(Intent) ServiceTestCase.bindService()}. This |
| 88 | allows you to set up your test environment, particularly your mock objects, before the Service |
| 89 | is started. |
| 90 | </p> |
| 91 | <p> |
| 92 | Notice that the parameters to <code>ServiceTestCase.bindService()</code>are different from |
| 93 | those for <code>Service.bindService()</code>. For the <code>ServiceTestCase</code> version, |
| 94 | you only provide an Intent. Instead of returning a boolean, |
| 95 | <code>ServiceTestCase.bindService()</code> returns an object that subclasses |
| 96 | {@link android.os.IBinder}. |
| 97 | </p> |
| 98 | <p> |
| 99 | The {@link android.test.ServiceTestCase#setUp()} method for {@link android.test.ServiceTestCase} |
| 100 | is called before each test. It sets up the test fixture by making a copy of the current system |
| 101 | Context before any test methods touch it. You can retrieve this Context by calling |
| 102 | {@link android.test.ServiceTestCase#getSystemContext()}. If you override this method, you must |
| 103 | call <code>super.setUp()</code> as the first statement in the override. |
| 104 | </p> |
| 105 | <p> |
| 106 | The methods {@link android.test.ServiceTestCase#setApplication(Application) setApplication()} |
| 107 | and {@link android.test.AndroidTestCase#setContext(Context)} setContext()} allow you to set |
| 108 | a mock Context or mock Application (or both) for the Service, before you start it. These mock |
| 109 | objects are described in <a href="#MockObjects">Mock object classes</a>. |
| 110 | </p> |
| 111 | <p> |
| 112 | By default, {@link android.test.ServiceTestCase} runs the test method |
| 113 | {@link android.test.AndroidTestCase#testAndroidTestCaseSetupProperly()}, which asserts that |
| 114 | the base test case class successfully set up a Context before running. |
| 115 | </p> |
| 116 | <h2 id="MockObjects">Mock object classes</h2> |
| 117 | <p> |
| 118 | <code>ServiceTestCase</code> assumes that you will use a mock Context or mock Application |
| 119 | (or both) for the test environment. These objects isolate the test environment from the |
| 120 | rest of the system. If you don't provide your own instances of these objects before you |
| 121 | start the Service, then {@link android.test.ServiceTestCase} will create its own internal |
| 122 | instances and inject them into the Service. You can override this behavior by creating and |
| 123 | injecting your own instances before starting the Service |
| 124 | </p> |
| 125 | <p> |
| 126 | To inject a mock Application object into the Service under test, first create a subclass of |
| 127 | {@link android.test.mock.MockApplication}. <code>MockApplication</code> is a subclass of |
| 128 | {@link android.app.Application} in which all the methods throw an Exception, so to use it |
| 129 | effectively you subclass it and override the methods you need. You then inject it into the |
| 130 | Service with the |
| 131 | {@link android.test.ServiceTestCase#setApplication(Application) setApplication()} method. |
| 132 | This mock object allows you to control the application values that the Service sees, and |
| 133 | isolates it from the real system. In addition, any hidden dependencies your Service has on |
| 134 | its application reveal themselves as exceptions when you run the test. |
| 135 | </p> |
| 136 | <p> |
| 137 | You inject a mock Context into the Service under test with the |
| 138 | {@link android.test.AndroidTestCase#setContext(Context) setContext()} method. The mock |
| 139 | Context classes you can use are described in more detail in |
| 140 | <a href="{@docRoot}tools/testing/testing_android.html#MockObjectClasses"> |
| 141 | Testing Fundamentals</a>. |
| 142 | </p> |
| 143 | <h2 id="TestAreas">What to Test</h2> |
| 144 | <p> |
| 145 | The topic <a href="{@docRoot}tools/testing/what_to_test.html">What To Test</a> |
| 146 | lists general considerations for testing Android components. |
| 147 | Here are some specific guidelines for testing a Service: |
| 148 | </p> |
| 149 | <ul> |
| 150 | <li> |
| 151 | Ensure that the {@link android.app.Service#onCreate()} is called in response to |
| 152 | {@link android.content.Context#startService(Intent) Context.startService()} or |
| 153 | {@link android.content.Context#bindService(Intent,ServiceConnection,int) Context.bindService()}. |
| 154 | Similarly, you should ensure that {@link android.app.Service#onDestroy()} is called in |
| 155 | response to {@link android.content.Context#stopService(Intent) Context.stopService()}, |
| 156 | {@link android.content.Context#unbindService(ServiceConnection) Context.unbindService()}, |
| 157 | {@link android.app.Service#stopSelf()}, or |
| 158 | {@link android.app.Service#stopSelfResult(int) stopSelfResult()}. |
| 159 | </li> |
| 160 | <li> |
| 161 | Test that your Service correctly handles multiple calls from |
| 162 | <code>Context.startService()</code>. Only the first call triggers |
| 163 | <code>Service.onCreate()</code>, but all calls trigger a call to |
| 164 | <code>Service.onStartCommand()</code>. |
| 165 | <p> |
| 166 | In addition, remember that <code>startService()</code> calls don't |
| 167 | nest, so a single call to <code>Context.stopService()</code> or |
| 168 | <code>Service.stopSelf()</code> (but not <code>stopSelf(int)</code>) |
| 169 | will stop the Service. You should test that your Service stops at the correct point. |
| 170 | </p> |
| 171 | </li> |
| 172 | <li> |
| 173 | Test any business logic that your Service implements. Business logic includes checking for |
| 174 | invalid values, financial and arithmetic calculations, and so forth. |
| 175 | </li> |
| 176 | </ul> |