2017-01-15 2 views
0

Ich habe ein Problem, bei dem mein Datenbank-Handle während meines Tests geschlossen wird und ich bin mir nicht sicher warum.SQLiteDatabase wird geschlossen, bevor der Test ausgeführt werden kann

Die @Before Verfahren läuft korrekt, aber die @Test Methode löst eine Ausnahme: Versuch ein bereits geschlossenes Objekt wieder zu öffnen. Ich schließe es nirgends in meinem Code, also bin ich mir nicht sicher, wie es geschlossen wird.

Die mit @Test markierte Methode ist bisher die einzige im Test, also laufen keine anderen Tests davor.

Kann mir jemand helfen zu verstehen, was hier passiert?

-Test

@RunWith(AndroidJUnit4.class) 
public class DatabaseTest { 

    private Database subject; 
    private SQLiteDatabase wDB; 

    public DatabaseTest(){ 

     DbHelper helper = new DbHelper(InstrumentationRegistry.getTargetContext()); 
     subject = new Database(helper); 
     wDB = helper.getWritableDatabase(); 

    } 


    // remove any preexisting records from the database 
    @Before 
    public void cleanSlate(){ 
     wDB.delete(Database.ITEMS_TABLE, null, null); 
    } 


    @Test 
    public void testInsert(){ 

     Cursor c; 
     Item i = getMockItem(); 
     subject.update(i); 

     // (per below) DatabaseTest.java:46: 
     c = wDB.query(Database.ITEM_TABLE,Database.ALL_COLUMNS,null,null,null,null,null); 

     //... 

Fehler

java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/user/0/com.example.app.debug/databases/storage.db 
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55) 
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314) 
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1257) 
at com.example.app.data.local.DatabaseTest.testInsert(DatabaseTest.java:46) 

Update-Methode

public void update(Item item){ 

     SQLiteDatabase wDB = helper.getWritableDatabase(); 

     ContentValues cv = entryToContentValues(item); 
     wDB.insertWithOnConflict(ITEM_TABLE, null, cv, SQLiteDatabase.CONFLICT_REPLACE); 

     wDB.close(); 
    } 
+0

Möglicherweise müssen Sie den Code für 'getMockItem()' und/oder 'subject.update (i)' anzeigen. Schließen Sie die Datenbank? Wenn ja, dann wäre das die wahrscheinliche Ursache. Sie könnten versuchen, "wDB = helper.getWritableDatabase();' kurz vor Zeile 46 einzufügen. – MikeT

+0

@MikeT Die Update-Methode ruft close() auf (Source wurde der Frage hinzugefügt), tut dies aber auf ihrer eigenen Instanz von SQLiteDatabase. Gilt close() global? – Stephen

+0

Kurz gesagt im Grunde ja. – MikeT

Antwort

0

Das Problem ist, dass Sie closin g die Datenbank in der update Methode und damit die Datenbank geschlossen wird, wenn Sie versuchen, die Abfrage in Zeile 46 auszuführen.

Eine Lösung wäre, die Datenbank in der Update-Methode nicht zu schließen. Sie sollten es jedoch schließen, wenn Sie mit der Datenbank fertig sind.

Eine andere Lösung könnte sein, getWriteableDatabase(); vor der Abfrage aber nach update zu rufen.

Andere Lösungen können bis zu einem Singleton reichen, so dass Sie nur eine einzelne Instanz/Verbindung haben und dann nur die Datenbank schließen, wenn die App zerstört wird (ich verwende diesen Ansatz in der App, die ich verwende).

P.S. Sie sollten auch Cursor schließen, dann sind sie fertig, weil sie verursachen können. Zu viele offene Fehler/Probleme. Persönlich neige ich dazu, den Cursor in die Aktivitäten onDestroy Methode zu setzen.

Verwandte Themen