2016-01-12 30 views
6

Próbuję uruchomić wiele testów przy użyciu Robolectric 3.0 + Gradle przy użyciu SQLite (OpenHelper) jako bazy danych. Uruchamianie każdego pojedynczego testu działa dobrze, ale uruchomienie całego zestawu testów zawsze powoduje wyjątek RuntimeException w drugim teście.Robolectric: uruchamianie wielu testów kończy się niepowodzeniem

To jest mój próbny manekin, który nie działa.

@RunWith(RobolectricGradleTestRunner.class) 
@Config(constants = BuildConfig.class, sdk = 21) 
public class Dummy { 


    @Before 
    public void setUp() throws Exception { 
     // setup activity ... 
    } 

    @Test 
    public void testA() throws Exception { 
     Assert.assertTrue(true); 
    } 

    @Test 
    public void testB() { 
     Assert.assertTrue(true); 
    } 
} 

Wyjątek

java.lang.RuntimeException: java.lang.IllegalStateException: Illegal connection pointer 1. Current pointers for thread Thread[pool-4-thread-1,5,main] [] 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections.execute(ShadowSQLiteConnection.java:470) 
    at org.robolectric.shadows.ShadowSQLiteConnection.nativeResetStatementAndClearBindings(ShadowSQLiteConnection.java:286) 
    at android.database.sqlite.SQLiteConnection.nativeResetStatementAndClearBindings(SQLiteConnection.java) 
    at android.database.sqlite.SQLiteConnection.releasePreparedStatement(SQLiteConnection.java:915) 
    at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:519) 
    at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588) 
    at android.database.sqlite.SQLiteProgram.__constructor__(SQLiteProgram.java:58) 
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java) 
    at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java) 
    at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469) 
    at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341) 
    at de.d360.android.sdk.v2.storage.db.datasource.AbstractDataSource.insert(AbstractDataSource.java:78) 
    at de.d360.android.sdk.v2.storage.db.datasource.QueueMessageDataSource.create(QueueMessageDataSource.java:100) 
    at de.d360.android.sdk.v2.net.Queue.addToHttpQueue(Queue.java:185) 
    at de.d360.android.sdk.v2.D360Events.sendEvent(D360Events.java:1636) 
    at de.d360.android.sdk.v2.D360Events.sendEvent(D360Events.java:1612) 
    at de.d360.android.sdk.v2.D360Events.sendEvent(D360Events.java:1651) 
    at de.d360.android.sdk.v2.D360Events.appInstanceUpdated(D360Events.java:359) 
    at de.d360.android.sdk.v2.crm.AppInstanceUpdater.sendUpdateEvent(AppInstanceUpdater.java:27) 
    at de.android.hotel.HotelApplication.onCreate(HotelApplication.java:281) 
    at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:140) 
    at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:433) 
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:240) 
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188) 
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 
Caused by: java.lang.IllegalStateException: Illegal connection pointer 1. Current pointers for thread Thread[pool-4-thread-1,5,main] [] 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections.getConnection(ShadowSQLiteConnection.java:333) 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections.getStatement(ShadowSQLiteConnection.java:340) 
    at org.robolectric.shadows.ShadowSQLiteConnection.stmt(ShadowSQLiteConnection.java:52) 
    at org.robolectric.shadows.ShadowSQLiteConnection.access$000(ShadowSQLiteConnection.java:33) 
    at org.robolectric.shadows.ShadowSQLiteConnection$16.call(ShadowSQLiteConnection.java:289) 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections$6.call(ShadowSQLiteConnection.java:452) 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections$6.call(ShadowSQLiteConnection.java:446) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:722) 

java.lang.RuntimeException: java.lang.RuntimeException: java.lang.IllegalStateException: Illegal connection pointer 1. Current pointers for thread Thread[pool-4-thread-1,5,main] [] 
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:244) 
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188) 
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140) 
Caused by: java.lang.RuntimeException: java.lang.IllegalStateException: Illegal connection pointer 1. Current pointers for thread Thread[pool-4-thread-1,5,main] [] 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections.execute(ShadowSQLiteConnection.java:470) 
    at org.robolectric.shadows.ShadowSQLiteConnection.nativeResetStatementAndClearBindings(ShadowSQLiteConnection.java:286) 
    at android.database.sqlite.SQLiteConnection.nativeResetStatementAndClearBindings(SQLiteConnection.java) 
    at android.database.sqlite.SQLiteConnection.releasePreparedStatement(SQLiteConnection.java:915) 
    at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:519) 
    at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588) 
    at android.database.sqlite.SQLiteProgram.__constructor__(SQLiteProgram.java:58) 
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java) 
    at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java) 
    at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1469) 
    at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341) 
    at de.d360.android.sdk.v2.storage.db.datasource.AbstractDataSource.insert(AbstractDataSource.java:78) 
    at de.d360.android.sdk.v2.storage.db.datasource.QueueMessageDataSource.create(QueueMessageDataSource.java:100) 
    at de.d360.android.sdk.v2.net.Queue.addToHttpQueue(Queue.java:185) 
    at de.d360.android.sdk.v2.D360Events.sendEvent(D360Events.java:1636) 
    at de.d360.android.sdk.v2.D360Events.sendEvent(D360Events.java:1612) 
    at de.d360.android.sdk.v2.D360Events.sendEvent(D360Events.java:1651) 
    at de.d360.android.sdk.v2.D360Events.appInstanceUpdated(D360Events.java:359) 
    at de.d360.android.sdk.v2.crm.AppInstanceUpdater.sendUpdateEvent(AppInstanceUpdater.java:27) 
    at de.android.hotel.HotelApplication.onCreate(HotelApplication.java:281) 
    at org.robolectric.internal.ParallelUniverse.setUpApplicationState(ParallelUniverse.java:140) 
    at org.robolectric.RobolectricTestRunner.setUpApplicationState(RobolectricTestRunner.java:433) 
    at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:240) 
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188) 
    at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
    at org.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68) 
    ... 1 more 
Caused by: java.lang.IllegalStateException: Illegal connection pointer 1. Current pointers for thread Thread[pool-4-thread-1,5,main] [] 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections.getConnection(ShadowSQLiteConnection.java:333) 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections.getStatement(ShadowSQLiteConnection.java:340) 
    at org.robolectric.shadows.ShadowSQLiteConnection.stmt(ShadowSQLiteConnection.java:52) 
    at org.robolectric.shadows.ShadowSQLiteConnection.access$000(ShadowSQLiteConnection.java:33) 
    at org.robolectric.shadows.ShadowSQLiteConnection$16.call(ShadowSQLiteConnection.java:289) 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections$6.call(ShadowSQLiteConnection.java:452) 
    at org.robolectric.shadows.ShadowSQLiteConnection$Connections$6.call(ShadowSQLiteConnection.java:446) 
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) 
    at java.util.concurrent.FutureTask.run(FutureTask.java:166) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:722) 

już próbowałem kilka rozwiązań takich jak resetowanie singleton z następującego kodu, który kończy się w FieldNotfoundException lub NullPointerException, więc nie działa.

@After 
public void finishComponentTesting() { 
    // sInstance is the static variable name which holds the singleton instance 
    resetSingleton(MySQLiteOpenHelper.class, "sInstance"); 
} 

private void resetSingleton(Class clazz, String fieldName) { 
    Field instance; 
    try { 
     instance = clazz.getDeclaredField(fieldName); 
     instance.setAccessible(true); 
     instance.set(null, null); 
    } catch (Exception e) { 
     throw new RuntimeException(); 
    } 
} 

Edit: stałe usuwając sendUpdateEvent() z D360Sdk za AppInstanceUpdater.

AppInstanceUpdater updater = D360Sdk.getCrmAppInstanceUpdater(); 
updater.setCustomId(Util.installId()); 
// updater.sendUpdateEvent(); 
+0

Ah, znowu trochę inicjalizacji biblioteki w klasie aplikacji. Spójrz na to rozwiązanie http://stackoverflow.com/questions/34695552/robolectric-with-activeandroid-setup-nullpointerexception-on-activeandroidrefle –

+0

+1 Dla twojego rozwiązania! Po dwóch dniach nieudanych ratujesz moje życie! Instancja resetowania była dokładnie tym, czego szukałem! –

Odpowiedz

5

To stare pytanie, ale może to rozwiązanie może pomóc komuś, ponieważ miałem do czynienia z podobnym problemem (dokładnie ten sam błąd).

Problem polega na tym, że podczas uruchamiania wielu przypadków testowych, które wielokrotnie uzyskują dostęp do bazy danych, pierwszy przypadek testowy otwiera połączenie z bazą danych i nie powoduje jej zamknięcia. Gdy drugi przypadek testowy próbuje ponownie nawiązać połączenie z bazą danych, nie powiedzie się.

Przeczytałem kilka rozwiązań i ostatecznie zorientowałem się, że problem polegał na wielokrotnym otwieraniu bazy danych. Tak aby uruchomić testy pomyślnie, należy wykonać następującą konfigurację w pliku TestCase.java (gdzie masz napisane swoje przypadków testowych):

@Before 
public void setUp() throws Exception { 
    //Get an instance of your implementation of SQLiteOpenHelper class. 
    //Let's assume the class name is MySQLiteHelper which extends SQLiteOpenHelper and has a function called getInstance 
    //which returns the instance of the SQLiteOpenHelper. 
    //Store this instance in a global variable in your TestCase.java file. 
    databaseHelper = MySQLiteHelper.getInstance(); 
} 

@After 
public void tearDown() throws Exception { 
    //use the instance created in setUp() function to close the database 
    databaseHelper.close(); 
} 

Powyższe dwie funkcje z adnotacją „@Before” i „@After” uruchamiane przed i po każdy przypadek testowy. Tak więc, po każdym przypadku testowym powinniśmy zamknąć połączenie z bazą danych. Pomocne linki:

This i this.

Proszę komentarz, jeśli coś jest nie tak w rozwiązaniu lub jeśli moje rozumienie tego błędu jest błędne.

+0

@Dawkodawca może skomentować tutaj, co nie działało. –