178 lines
6.4 KiB
Java
178 lines
6.4 KiB
Java
/*
|
|
* 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 java.lang.reflect.Field;
|
|
|
|
import android.app.Application;
|
|
import android.app.Instrumentation;
|
|
import android.content.Context;
|
|
|
|
/**
|
|
* This test case provides a framework in which you can test Application classes in
|
|
* a controlled environment. It provides basic support for the lifecycle of a
|
|
* Application, and hooks by which you can inject various dependencies and control
|
|
* the environment in which your Application is tested.
|
|
*
|
|
* <p><b>Lifecycle Support.</b>
|
|
* Every Application is designed to be accessed within a specific sequence of
|
|
* method calls (see {@link android.app.Application} for more details).
|
|
* In order to support the lifecycle of a Application, this test case will make the
|
|
* following calls at the following times.
|
|
*
|
|
* <ul><li>The test case will not call onCreate() until your test calls
|
|
* {@link #createApplication()}. This gives you a chance
|
|
* to set up or adjust any additional framework or test logic before
|
|
* onCreate().</li>
|
|
* <li>After your test completes, the test case {@link #tearDown} method is
|
|
* automatically called, and it will stop & destroy your application by calling its
|
|
* onDestroy() method.</li>
|
|
* </ul>
|
|
*
|
|
* <p><b>Dependency Injection.</b>
|
|
* Every Application has one inherent dependency, the {@link android.content.Context Context} in
|
|
* which it runs.
|
|
* This framework allows you to inject a modified, mock, or isolated replacement for this
|
|
* dependencies, and thus perform a true unit test.
|
|
*
|
|
* <p>If simply run your tests as-is, your Application will be injected with a fully-functional
|
|
* Context.
|
|
* You can create and inject alternative types of Contexts by calling
|
|
* {@link AndroidTestCase#setContext(Context) setContext()}. You must do this <i>before</i> calling
|
|
* startApplication(). 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 ApplicationTestCase<T extends Application> extends AndroidTestCase {
|
|
|
|
Class<T> mApplicationClass;
|
|
|
|
private Context mSystemContext;
|
|
|
|
public ApplicationTestCase(Class<T> applicationClass) {
|
|
mApplicationClass = applicationClass;
|
|
}
|
|
|
|
private T mApplication;
|
|
private boolean mAttached = false;
|
|
private boolean mCreated = false;
|
|
|
|
/**
|
|
* @return Returns the actual Application under test.
|
|
*/
|
|
public T getApplication() {
|
|
return mApplication;
|
|
}
|
|
|
|
/**
|
|
* This will do the work to instantiate the Application under test. After this, your test
|
|
* code must also start and stop the Application.
|
|
*/
|
|
@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();
|
|
}
|
|
|
|
/**
|
|
* Load and attach the application under test.
|
|
*/
|
|
private void setupApplication() {
|
|
mApplication = null;
|
|
try {
|
|
mApplication = (T) Instrumentation.newApplication(mApplicationClass, getContext());
|
|
} catch (Exception e) {
|
|
assertNotNull(mApplication);
|
|
}
|
|
mAttached = true;
|
|
}
|
|
|
|
/**
|
|
* Start the Application under test, in the same way as if it was started by the system.
|
|
* If you use this method to start the Application, it will automatically
|
|
* be stopped by {@link #tearDown}. If you wish to inject a specialized Context for your
|
|
* test, by calling {@link AndroidTestCase#setContext(Context) setContext()},
|
|
* you must do so before calling this method.
|
|
*/
|
|
final protected void createApplication() {
|
|
assertFalse(mCreated);
|
|
|
|
if (!mAttached) {
|
|
setupApplication();
|
|
}
|
|
assertNotNull(mApplication);
|
|
|
|
mApplication.onCreate();
|
|
mCreated = true;
|
|
}
|
|
|
|
/**
|
|
* This will make the necessary calls to terminate the Application under test (it will
|
|
* call onTerminate(). 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.
|
|
*/
|
|
final protected void terminateApplication() {
|
|
if (mCreated) {
|
|
mApplication.onTerminate();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shuts down the Application 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 {
|
|
terminateApplication();
|
|
mApplication = 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(ApplicationTestCase.class);
|
|
|
|
super.tearDown();
|
|
}
|
|
|
|
/**
|
|
* Return a real (not mocked or instrumented) system Context that can be used when generating
|
|
* Mock or other Context objects for your Application under test.
|
|
*
|
|
* @return Returns a reference to a normal Context.
|
|
*/
|
|
public Context getSystemContext() {
|
|
return mSystemContext;
|
|
}
|
|
|
|
/**
|
|
* This test simply confirms that the Application class can be instantiated properly.
|
|
*
|
|
* @throws Exception
|
|
*/
|
|
final public void testApplicationTestCaseSetUpProperly() throws Exception {
|
|
setupApplication();
|
|
assertNotNull("Application class could not be instantiated successfully", mApplication);
|
|
}
|
|
}
|