Robolectric: running multiple tests fails

冷暖自知 提交于 2019-12-23 06:58:36

问题


I am trying to run multiple tests with Robolectric 3.0 + Gradle using SQLite (OpenHelper) as database. Running each single tests works fine, but starting the whole test suite always results in RuntimeException in the 2nd test.

This is my test dummy, which does not work.

@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);
    }
}

Exception

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)

Already tried some solutions like reseting singleton with the following code, which ends in FieldNotfoundException or NullPointerException, so did not work.

@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: fixed it by removing sendUpdateEvent() of D360Sdk's AppInstanceUpdater.

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

回答1:


It is an old question but maybe this solution can help someone as I was facing similar issue (exactly same error).

The issue is that while running multiple test cases which are accessing database multiple times, the first test case opens the connection to the database and does not close it. When second test case tries to open database connection again it fails.

I read some solutions and finally figured out that the issue was with opening database multiple times. So to run tests successfully, do the following configuration in your TestCase.java file (where you have written your test cases):

@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();
}

The above two functions annotated with "@Before" and "@After" run before and after every test case. So, for after each test case we should close the database connection.

This and this links helped.

Please comment if there is something wrong in the solution or if my understanding of this error is wrong.



来源:https://stackoverflow.com/questions/34742685/robolectric-running-multiple-tests-fails

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!