9

Ich habe eine Klasse, die den MediaStore nach Bildern abfragt. Zum Beispiel habe ich Code, der wie someContentResolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, ...) aussieht. Ich möchte testen, dass unter anderem meine Anfragen an den MediaStore korrekt sind.ist es möglich, den MediaStore mit einem Test-Doppel zu ersetzen?

Was ich bisher in meinem Test gemacht habe, ist dies:

ContentResolver resolver = new Activity().getContentResolver(); 
ContentValues values = new ContentValues(); 
values.put(MediaStore.Images.Media.DATA, 
      "/fake/path/file1.jpg"); 
values.put(MediaStore.Images.Media.DATE_ADDED, 
      fakeTime.getTime()); 
resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
       values); 

ich diesen Resolver in meine Klasse zu injizieren, die auf eine Abfrage durchführt. Die Abfrage gibt jedoch null zurück. Ich sah diesen Beitrag: http://ikaruga2.wordpress.com/2013/07/29/roboelectric-and-contentresolverscontentproviders/, die die Content-Provider mit ShadowContentResolver registrieren sagt, so etwas wie:

ShadowContentResolver.registerProvider(MediaStore.AUTHORITY, <SOMETHING_GOES_HERE>); 

aber ich weiß nicht, was für die Inhalte-Anbieter zu setzen. Vielleicht ein MediaStore Objekt verwenden? Nein, es ist kein ContentProvider. Vielleicht ist es MediaProvider? Das Symbol kann aus irgendeinem Grund nicht aufgelöst werden.

An dieser Stelle habe ich ernsthafte Zweifel, dass dies sogar im entferntesten der richtige Ansatz ist. Kann mich jemand in die richtige Richtung lenken?

mit Robolectric 2.4 Snapshot und API 19.

+0

Haben Sie schon eine Lösung gefunden? –

+0

@SebastianRoth nein, habe ich nicht. – Kevin

Antwort

0

Ich war mit Mediastore ein ähnliches Problem hat, in meinem Fall eine Klasse versucht, die Mediastore durch einen managedQuery zuzugreifen. Beim Ausführen eines Tests, der diesen Codepfad durchlaufen hat, ist der Test mit einer NPE fehlgeschlagen, da die Abfrage wie in Ihrem Fall null zurückgegeben hat.

Die beanstandeten Methode

public String getPath(Uri uri, Activity activity) { 
    String[] projection = { MediaColumns.DATA }; 
    Cursor cursor = activity 
      .managedQuery(uri, projection, null, null, null); 
    int column_index = cursor.getColumnIndexOrThrow(MediaColumns.DATA); 
    cursor.moveToFirst(); 
    return cursor.getString(column_index); 
} 

Da Sie bereits (ich auf mein Projekt injizieren Abhängigkeiten mit Dolch) injizieren der Resolver, könnten Sie entweder wollen sie verspotten, wenn es Ihnen passt (via Mockito zum Beispiel) oder verspotten Sie es teilweise, so dass die beanstandete Methode einen verwendbaren Rückgabewert vorgibt.

PhotoUtilities pu=Mockito.spy(new PhotoUtilities()); 
Mockito.doReturn(Constants.getDataDir().getAbsolutePath()+"/aaa.txt"). 
when(pu).getPath(Mockito.isA(Uri.class), Mockito.isA(Activity.class)); 

Auf diese Weise, wenn der Test getPath() zu laufen versucht, wäre es nicht die Abfrage ausführen, aber den Standard-Rückgabewert in dem Teil Mock Satz verwendet werden soll, ist der Test so dass auf gehen.

Ich weiß, dass es nicht genau das ist, was Sie suchen, aber es könnte Ihren Bedürfnissen entsprechen, wie es für mich getan hat.

+0

Ich möchte tatsächlich die Abfrage validieren. Danke für die Antwort! – Kevin

1

Sie können sich auf ShadowContentResolver.setCursor(Uri, BaseCursor) und RoboCursor verlassen, um Testdaten zu erstellen und Abfragen zu verifizieren. RoboCursor bietet keine vollständige Implementierung einiger Methoden, sodass Sie sie entweder überschreiben und ignorieren oder sinnvolle Aktionen ausführen können. RoboCursor erweitert BaseCursor, überschreiben setQuery() ermöglicht es Ihnen, Abfragen abzufangen und zu verifizieren oder etwas zu tun. Verwenden von Robolectric 3.0.

RoboCursor cursor = new RoboCursor() { 
    @Override 
    public void registerContentObserver(ContentObserver observer) { 
     // no op 
    } 

    @Override 
    public void unregisterContentObserver(ContentObserver observer) { 
     // no op 
    } 

    @Override 
    public void registerDataSetObserver(DataSetObserver observer) { 
     // no op 
    } 

    @Override 
    public void unregisterDataSetObserver(DataSetObserver observer) { 
     // no op 
    } 

    @Override 
    public boolean isClosed() { 
     return true; 
    } 
}; 
cursor.setColumnNames(Arrays.asList(MediaStore.Images.Media._ID, 
     MediaStore.Images.Media.BUCKET_DISPLAY_NAME)); 
cursor.setResults(new Object[][]{ 
     new Object[]{1L, "WhatsApp"}, 
     new Object[]{2L, "Photos"}, 
     new Object[]{3L, "WhatsApp"} 
}); 
shadowOf(ShadowApplication.getInstance().getContentResolver()) 
     .setCursor(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, cursor);