/* * Copyright (C) 2007 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.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.pm.ProviderInfo; import android.content.res.Resources; import android.test.mock.MockContext; import android.test.mock.MockContentResolver; import android.database.DatabaseUtils; import java.io.File; /** * This test case class provides a framework for testing a single * {@link ContentProvider} and for testing your app code with an * isolated content provider. Instead of using the system map of * providers that is based on the manifests of other applications, the test * case creates its own internal map. It then uses this map to resolve providers * given an authority. This allows you to inject test providers and to null out * providers that you do not want to use. *

* This test case also sets up the following mock objects: *

* *

* This framework is set up automatically by the base class' {@link #setUp()} method. If you * override this method, you must call the super method as the first statement in * your override. *

*

* In order for their tests to be run, concrete subclasses must provide their own * constructor with no arguments. This constructor must call * {@link #ProviderTestCase2(Class, String)} as its first operation. *

* For more information on content provider testing, please see * Content Provider Testing. */ public abstract class ProviderTestCase2 extends AndroidTestCase { Class mProviderClass; String mProviderAuthority; private IsolatedContext mProviderContext; private MockContentResolver mResolver; private class MockContext2 extends MockContext { @Override public Resources getResources() { return getContext().getResources(); } @Override public File getDir(String name, int mode) { // name the directory so the directory will be separated from // one created through the regular Context return getContext().getDir("mockcontext2_" + name, mode); } @Override public Context getApplicationContext() { return this; } } /** * Constructor. * * @param providerClass The class name of the provider under test * @param providerAuthority The provider's authority string */ public ProviderTestCase2(Class providerClass, String providerAuthority) { mProviderClass = providerClass; mProviderAuthority = providerAuthority; } private T mProvider; /** * Returns the content provider created by this class in the {@link #setUp()} method. * @return T An instance of the provider class given as a parameter to the test case class. */ public T getProvider() { return mProvider; } /** * Sets up the environment for the test fixture. *

* Creates a new * {@link android.test.mock.MockContentResolver}, a new IsolatedContext * that isolates the provider's file operations, and a new instance of * the provider under test within the isolated environment. *

* * @throws Exception */ @Override protected void setUp() throws Exception { super.setUp(); mResolver = new MockContentResolver(); final String filenamePrefix = "test."; RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext( new MockContext2(), // The context that most methods are //delegated to getContext(), // The context that file methods are delegated to filenamePrefix); mProviderContext = new IsolatedContext(mResolver, targetContextWrapper); mProvider = createProviderForTest(mProviderContext, mProviderClass, mProviderAuthority); mResolver.addProvider(mProviderAuthority, getProvider()); } /** * Creates and sets up a new instance of the provider. */ static T createProviderForTest( Context context, Class providerClass, String authority) throws IllegalAccessException, InstantiationException { T instance = providerClass.newInstance(); ProviderInfo providerInfo = new ProviderInfo(); providerInfo.authority = authority; instance.attachInfoForTesting(context, providerInfo); return instance; } /** * Tears down the environment for the test fixture. *

* Calls {@link android.content.ContentProvider#shutdown()} on the * {@link android.content.ContentProvider} represented by mProvider. */ @Override protected void tearDown() throws Exception { mProvider.shutdown(); super.tearDown(); } /** * Gets the {@link MockContentResolver} created by this class during initialization. You * must use the methods of this resolver to access the provider under test. * * @return A {@link MockContentResolver} instance. */ public MockContentResolver getMockContentResolver() { return mResolver; } /** * Gets the {@link IsolatedContext} created by this class during initialization. * @return The {@link IsolatedContext} instance */ public IsolatedContext getMockContext() { return mProviderContext; } /** *

* Creates a new content provider of the same type as that passed to the test case class, * with an authority name set to the authority parameter, and using an SQLite database as * the underlying data source. The SQL statement parameter is used to create the database. * This method also creates a new {@link MockContentResolver} and adds the provider to it. *

*

* Both the new provider and the new resolver are put into an {@link IsolatedContext} * that uses the targetContext parameter for file operations and a {@link MockContext} * for everything else. The IsolatedContext prepends the filenamePrefix parameter to * file, database, and directory names. *

*

* This is a convenience method for creating a "mock" provider that can contain test data. *

* * @param targetContext The context to use as the basis of the IsolatedContext * @param filenamePrefix A string that is prepended to file, database, and directory names * @param providerClass The type of the provider being tested * @param authority The authority string to associated with the test provider * @param databaseName The name assigned to the database * @param databaseVersion The version assigned to the database * @param sql A string containing the SQL statements that are needed to create the desired * database and its tables. The format is the same as that generated by the * sqlite3 tool's .dump command. * @return ContentResolver A new {@link MockContentResolver} linked to the provider * * @throws IllegalAccessException * @throws InstantiationException */ public static ContentResolver newResolverWithContentProviderFromSql( Context targetContext, String filenamePrefix, Class providerClass, String authority, String databaseName, int databaseVersion, String sql) throws IllegalAccessException, InstantiationException { MockContentResolver resolver = new MockContentResolver(); RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext( new MockContext(), // The context that most methods are delegated to targetContext, // The context that file methods are delegated to filenamePrefix); Context context = new IsolatedContext(resolver, targetContextWrapper); DatabaseUtils.createDbFromSqlStatements(context, databaseName, databaseVersion, sql); T provider = createProviderForTest(context, providerClass, authority); resolver.addProvider(authority, provider); return resolver; } }