2013-08-02 15 views
12

Ho notato che di tanto in tanto c'è una domanda sull'utilizzo di Robolectric per testare ContentProvider personalizzati. Tuttavia, non c'è mai stata una risposta concreta e non ambigua su come farlo correttamente. Ho inciampato su 2 diversi approcci:Contenuto di materiale elettrico Test del fornitore

Tuttavia, sto diventando un java.lang.InstantiationException con entrambi gli approcci. Ci sono stati alcuni messaggi SO che affermano che ciò è dovuto a SQLiteDatabase.rawQueryWithFactory (SQLiteDatabase.java) non sottoposto a override in Robolectric (Android + Robolectric - RuntimeException/InstantiationException in queryBuilder.query() in ContentProvider).

Suppongo che la mia domanda sia: esistono soluzioni alternative preimpostate che rendono possibile il test dei ContentProvider. O ci sono altri approcci che sono migliori di quelli menzionati sopra.

+0

Suggerisco di non utilizzare il primo collegamento - il codice è completamente stupido e non verrà nemmeno compilato. –

risposta

5

Tutto quello che dovete fare, è istituito ShadowContentResolver prima della prova, in modo che l'autorità correttamente associato della vostra ContentProvider con ContentProvider stessa. Ecco un esempio:

ShadowContentResolver.registerProvider(
     "com.example.provider", //authority of your provider 
     contentProvider //instance of your ContentProvider (you can just use default constructor)  
); 

Il modo più semplice è quello di mettere questa roba in qualche @Before metodo set-up annotato. Tuttavia, il modo più corretto (e quindi migliore a lungo termine) è quello di inserire questo nel metodo TestApplication#onCreate, quindi questa configurazione verrà utilizzata da tutti i test dell'applicazione.

+0

Ho inserito il codice precedente in 'TestApplication # onCreate' ma non è stato possibile utilizzare il provider di contenuti per tutti i test. Dopo il primo test, il database verrà rimosso: https://github.com/robolectric/robolectric/issues/1082. Hai avuto successo con più di 2 test per il fornitore di contenuti con Robolectric? –

+1

@HieuRocker sì, lo so. Se ti ho capito bene, allora ti sei sbagliato un po '- dovrebbe essere previsto un comportamento per i test da ripulire dopo l'esecuzione. Crea il tuo database ogni volta con il metodo '@ Before' –

+0

W00t, potrei risolvere il problema in base al tuo suggerimento. È venuto fuori perché nel ContentProvider ho inizializzato 'SQLiteOpenHelper' usando il modello singleton. Fa in modo che Robolectric non riesca a ricreare il database per ogni test. Molte grazie. –

10

Questa è la prova Robolectric che ha funzionato bene per me:

import android.content.ContentResolver; 
import android.database.Cursor; 
import android.net.Uri; 

import org.joda.time.LocalDate; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.robolectric.Robolectric; 
import org.robolectric.RobolectricTestRunner; 
import org.robolectric.annotation.Config; 
import org.robolectric.shadows.ShadowContentResolver; 

import co.tomup.app.db.DbSchema; 
import co.tomup.app.db.TomupContentProvider; 
import co.tomup.app.db.model.CalendarDay; 
import co.tomup.app.db.tables.CalendarDayTable; 

import static org.junit.Assert.assertEquals; 
import static org.junit.Assert.assertTrue; 

@Config(emulateSdk = 18) 
@RunWith(RobolectricTestRunner.class) 
public class CalendarDayProviderTest { 

    private ContentResolver mContentResolver; 
    private ShadowContentResolver mShadowContentResolver; 
    private TomupContentProvider mProvider; 

    @Before 
    public void setup() { 
     mProvider = new TomupContentProvider(); 
     mContentResolver = Robolectric.application.getContentResolver(); 
     mShadowContentResolver = Robolectric.shadowOf(mContentResolver); 
     mProvider.onCreate(); 
     ShadowContentResolver.registerProvider(DbSchema.AUTHORITY, mProvider); 
    } 

    @Test 
    public void testInsertAndDelete() { 
     // insert 
     CalendarDay calendarDay = new CalendarDay(); 
     calendarDay.setId(1L); 
     calendarDay.setDay(new LocalDate()); 
     calendarDay.setMoonPhase("new"); 
     calendarDay.setSunrise(1); 
     calendarDay.setSunset(100); 
     Uri insertionId = mContentResolver.insert(CalendarDayTable.CONTENT_URI, 
       calendarDay.toSQLiteContentValues()); 
     Cursor cursorCheck = mShadowContentResolver.query(CalendarDayTable.CONTENT_URI, 
       null, null, null, null); 
     while (cursorCheck.moveToNext()) { 
      CalendarDay calendarDayCheck = CalendarDay.fromSQLiteCursor(cursorCheck); 
      assertEquals(calendarDay, calendarDayCheck); 
     } 
     assertTrue(cursorCheck.getCount() > 0); 
     // delete 
     mShadowContentResolver.delete(insertionId, 
       null, null); 
     cursorCheck = mShadowContentResolver.query(CalendarDayTable.CONTENT_URI, 
       null, null, null, null); 
     assertTrue(cursorCheck.getCount() == 0); 
    } 
} 
+0

Grazie per la risposta. Sto contando di più sull'apprendimento di Android tramite robolectric. Mi stanco di andare avanti e indietro con l'emulatore. E questa risposta mi sta aiutando a utilizzare e testare contentprovider. :) –

+4

Nota questa risposta è per RoboElectric 2.4, se si utilizza 3.0 quindi utilizzare https://github.com/robolectric/robolectric/wiki/2.4-to-3.0-Upgrade-Guide per trovare gli equivalenti 3.0. – Benjamin

+0

@ Benjamin sai se c'è un esempio con 3.0? Le uniche modifiche che devi apportare sono i nomi delle classi e delle annotazioni? Ecco le modifiche che ho interpretato dal documento -> cambia il runner di test in RoboelectricGradleTestRunner, e forse cambia getApplication in getShadowApplication. È corretto? – user1743524

Problemi correlati