Monday, March 28, 2011

ContentProviderのテストの仕方

今回,BottomPriceProvider というContentProviderの単体テストを行なう BottomPrivceProviderTest を作成してみましたので,そのメモを記していきます。

クラスの作成

ProviderTestCase2>T extends android.content.ContentProvider<を継承して作成します。
public class BottomPriceProviderTest extends ProviderTestCase2 {
...
}

コンストラクタの生成

super class から コンストラクタを自動生成すると,次のようなコードが生成されます。
 public BottomPriceProviderTest(Class providerClass,
            String providerAuthority) {
        super(providerClass, providerAuthority);
        // TODO Auto-generated constructor stub
    }
面倒なので,引数を指定しない版も作成しておきます。
 public BottomPriceProviderTest() {
        super(BottomPriceProvider.class, BottomPriceProvider.AUTHORITY);
        // TODO Auto-generated constructor stub
    }
ここでの,BottomPriceProvider.AUTHORITY は ContentProviderを提供する際に指定するContentのAuthority名です。

setUp, tearDown

setUpでは,フィールド mMockContext にgetMockContext()で得られるContextを格納しておきます。
tearDownでは特になにもしません。
    private Context mMockContext;
    @Override
    protected void setUp() throws Exception {
        // TODO Auto-generated method stub
        super.setUp();
        mMockContext = getMockContext();
    }

    @Override
    protected void tearDown() throws Exception {
        // TODO Auto-generated method stub
        super.tearDown();
    }

テスト

まずは簡単なところで,insert/query/deleteのテストを書いてみます。 テスト用のContentValuesを挿入,検索し,その検索結果が挿入したContentValuesの内容と一致することを確認し,最後にテスト用ContentValuesを削除します。
    public void testInsertDeleteRecord() {
        final ContentResolver resolver = mMockContext.getContentResolver();
        final Uri uri = BottomPrice.Prices.CONTENT_URI;
        ContentValues cv = new ContentValues();
        int price = 480;
        String jan_code_str = "4901111725133";
        cv.put(BottomPrice.Prices.PRICE, price);
        cv.put(BottomPrice.Prices.JAN_CODE, jan_code_str);
        Uri insertUri = resolver.insert(uri, cv);
        String price_id = insertUri.getPathSegments().get(1);
        
        // Query
        Uri queryUri = Uri.withAppendedPath(uri, price_id);
        String[] projection = new String[] {
                BottomPrice.Prices._ID,
                BottomPrice.Prices.PRICE,
                BottomPrice.Prices.JAN_CODE,
            };
        Cursor c = resolver.query(queryUri, projection, null, null, null);
        assertEquals("query resuult", 1, c.getCount());
        c.moveToFirst();
        assertEquals("Jan Code", jan_code_str, c.getString(c.getColumnIndex(BottomPrice.Prices.JAN_CODE)));
        assertEquals("Price", price, c.getInt(c.getColumnIndex(BottomPrice.Prices.PRICE)));
        c.close();
        
        resolver.delete(queryUri, null, null);
    }

実際にテストを実行してみましょう。
テスト Errorとなり,Failure Trace をみると
android.database.SQLException: Failed to insert row into content://com.damburisoft.android.app.bottomrpice.provider.bottompriceprovider/prices
at com.damburisoft.android.app.bottomrpice.provider.BottomPriceProvider.insert(BottomPriceProvider.java:107)
at android.content.ContentProvider$Transport.insert(ContentProvider.java:150)
at android.content.ContentResolver.insert(ContentResolver.java:629)
at com.damburisoft.android.provider.BottomPriceProviderTest.testInsertDeleteRecord(BottomPriceProviderTest.java:50)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:430)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
とあるので,これを直していくことによって自分のContentProviderを創り上げていきます。

No comments: