2012-09-27 32 views
2

我目前正在測試Android的ContentProvider,並遇到一些嘲笑它的問題。我已經在互聯網上花了幾天時間,但除了Android Developer Site的介紹外沒有找到任何有用的例子。如何設置Android的MockContentProvider

我實現了一個ContentProvider並編寫了一些測試。一切工作在這裏都很好。測試結果符合我的期望。

public class DirectMessageProviderTest extends ProviderTestCase2<DirectMessageProvider>{ 

    @SmallTest 
    public void testInsert() { 
     Log.d(TAG, "testInsert"); 

     /* 
     * result retrieves twitterId for the newly inserted item 
     */ 
     Uri result = provider.insert(
       DirectMessageProvider.CONTENT_URI, 
       createContentValues()); 

     Log.i(TAG, "INSERT; id for newly inserted item: " + result); 

     assertNotNull("INSERT!!! failed", result); 

     if (result != null) { 
      isDirectMessageInserted = true; 
     } 
    } 

    @SmallTest 
    public void testQuery() { 
     Log.d(TAG, "testQuery"); 

     Uri uri = Uri.withAppendedPath(
       DirectMessageProvider.CONTENT_URI, 
       String.valueOf(directMessage.getTwitterId())); 

     /* 
     * result retrieves a cursor or null 
     */ 
     Cursor result = provider.query(
       uri, 
       null, 
       null, 
       null, 
       null); 

     Log.i(TAG, "QUERY; number of rows inside the cursor: " + result.getCount()); 

     int expected = isDirectMessageInserted ? 1 : 0; 

     assertEquals("QUERY!!! failed", expected, result.getCount()); 
    } 
} 

我還實現了一個包含ContentProvider的類,並提供比刪除,插入,查詢和更新更復雜的方法。看一看!

public class DirectMessageDataAccessImpl implements 
     DirectMessageDataAccessInterface { 

    @Override 
    public boolean isStored(TwitterDirectMessage directMessage) 
      throws DataAccessException { 
     Log.d(TAG, "isStored"); 

     try { 
      Uri uri = Uri.withAppendedPath(
        DirectMessageProvider.CONTENT_URI, 
        String.valueOf(directMessage.getTwitterId())); 

      Cursor cursor = resolver.query(
        uri, 
        null, 
        null, 
        null, 
        null); 

      cursor.moveToFirst(); 

      boolean result = (cursor.getCount() > 0 ? true: false); 

      cursor.close(); 

      return result; 
     } catch (Exception e) { 
      Log.e(TAG, e.getMessage(), e); 
      throw new DataAccessException(e.getMessage()); 
     } 
    } 
} 

最後我們來談談我的問題,爲這堂課寫作測試。我想使用模擬的ContentResolver爲這個類編寫獨立的測試。我發現這個[示例](http://www.androidadb.com/source/npr-android-app-read-only/Npr_Test/src/org/npr/android/util/PlaylistProviderTest.java.html)互聯網,並試圖使用MockContentResolver。

首先,我創建了一個新的ContentProvider,它將從受測試的類中檢索刪除,插入,查詢和更新調用,從而一次又一次地創建相同的答案。

public class DirectMessageDataAccessTest extends ProviderTestCase2<DirectMessageProvider>{ 

    private ContentProvider provider = new ContentProvider() { 

     @Override 
     public int update(Uri uri, ContentValues values, String selection, 
       String[] selectionArgs) { 
      Log.d(TAG, "update"); 
      return 0; 
     } 

     @Override 
     public Cursor query(Uri uri, String[] projection, String selection, 
       String[] selectionArgs, String sortOrder) { 
      Log.w(TAG, "query"); 
      return null; 
     } 

     @Override 
     public boolean onCreate() { 
      Log.d(TAG, "onCreate"); 
      return false; 
     } 

     @Override 
     public Uri insert(Uri uri, ContentValues values) { 
      Log.d(TAG, "insert"); 
      return null; 
     } 

     @Override 
     public String getType(Uri uri) { 
      Log.d(TAG, "getType"); 
      return null; 
     } 

     @Override 
     public int delete(Uri uri, String selection, String[] selectionArgs) { 
      Log.d(TAG, "delete"); 
      return 0; 
     } 
    }; 
} 

在此之後,我修改我的設置方法,以創造一個MockContentResolver並添加上述

@Override 
protected void setUp() throws Exception { 
    super.setUp(); 

    /* 
    * MockContentResolver overrides Android's normal way of resolving providers by authority 
    */ 
    MockContentResolver resolver = new MockContentResolver(); 

    /* 
    * Adds access to a provider based on its authority 
    */ 
    resolver.addProvider(DirectMessageProvider.AUTHORITY, provider);   

    context = new IsolatedContext(resolver, getContext()); 

    this.setContext(context); 
} 

最後但並非最不重要的,我寫了一個測試案例我isStored方法我的ContentProvider。

public void testIsStored() { 
    Log.d(TAG, "testIsStored"); 

    TwitterDirectMessage directMessage = new TwitterDirectMessage(); 

    directMessage.setTwitterId(123456); 

    DirectMessageDataAccessInterface dataAccess = 
      new DirectMessageDataAccessImpl(context); 

    try { 
     assertFalse(dataAccess.isStored(directMessage)); 
    } catch (DataAccessException e) { 
     e.printStackTrace(); 
     fail("..."); 
    } 
} 

不幸的是,android.content.ContentProvider總是拋出一個NullPointerException。我在DirectMessageDataAccessImpl

E/DirectMessageDataAccessImpl(1758): null 
E/DirectMessageDataAccessImpl(1758): java.lang.NullPointerException 
E/DirectMessageDataAccessImpl(1758): at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:284) 
E/DirectMessageDataAccessImpl(1758): at android.content.ContentProvider$Transport.query(ContentProvider.java:177) 
E/DirectMessageDataAccessImpl(1758): at android.content.ContentResolver.query(ContentResolver.java:311) 
E/DirectMessageDataAccessImpl(1758): at xxx.xxxxx.xxxxxxx.app.database.dataaccess.implementation.DirectMessageDataAccessImpl.isStored(DirectMessageDataAccessImpl.java:72) 
E/DirectMessageDataAccessImpl(1758): at xxx.xxxxx.xxxxxxx.app.test.dataaccess.DirectMessageDataAccessTest.testIsStored(DirectMessageDataAccessTest.java:107) 

回答

0

在構造函數中72排隊叫號resolver.query(...)你應該設置

public YourClass() { 
    super(DBProvider.class, "com.yourpackage.main");// class of Your Content provider and application package 
} 

,然後就打電話

MockContentResolver mockContentResolver = getMockContentResolver(); 
assertNotNull(mockContentResolver); 
在測試

+0

有什麼辦法注入我自己的提供者以獲得靜態結果?只要我添加'addProvider',我就會得到上面的NullPointerException。 –

+0

你在這裏添加你自己的提供者 - > super(DBProvider.class,「com.yourpackage.main」); MockContentResolver將繼續引用您的提供者 – Yahor10