I made an application that copies a database that has been premade and then allows you to run the various queries/methods for an SQLiteDatabase (insert, update, etc.) with SQLTest as its main activity. I then made a test (called SQLTestCase, which I know is no appropriate, but I’m new to testing) which has a test suite calling up a randomTest() method that randomly picks a test to perform. The odd thing is that I get an error saying:
java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/com.example.sql2/databases/os.sqlite
at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1310)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1253)
at com.example.sql2.test.SQLTestCase.randomTest(SQLTestCase.java:236)
at com.example.sql2.test.SQLTestCase.testSuite(SQLTestCase.java:38)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1584)
The error shows up on two lines of code:
public void testSuite()
{
int length = 100;
for (int x = 0; x < length; x++)
{
randomTest(); // Here
}
}
public void randomTest()
{
...
String sql = "SELECT COUNT(*) AS NumberOfRecords FROM" + SQLAdapter.TABLE_OS;
Cursor cursor = activity.accessAdapter().accessHelper().accessDatabase().rawQuery(sql, null); //Here
...
I know that the problem lies on the initialization of the cursor, because by commenting that out, the test runs fine. Anyone know the problem? I looked over my code hoping to find a place where I closed the database early, but I don’t see anything. I’ll try and provide what you need. Let me know if there is more code necessary to solve this problem.
public class SQLTestCase extends ActivityInstrumentationTestCase2<SQLTest>
{
SQLTest activity;
public SQLTestCase()
{
super(SQLTest.class);
}
protected void setUp() throws Exception
{
super.setUp();
setActivityInitialTouchMode(false);
activity = getActivity();
}
...
public void testSuite()
{
int length = 100;
for (int x = 0; x < length; x++)
{
randomTest();
}
}
...
public void randomTest()
{
String name = "", field = "";
Random rand = new Random();
int randOp = rand.nextInt(5);
int randName, randField, id;
String sql = "SELECT COUNT(*) AS NumberOfRecords FROM" + SQLAdapter.TABLE_OS;
Cursor cursor = activity.accessAdapter().accessHelper().accessDatabase().rawQuery(sql, null);
switch (randOp)
{
case 0:
randName = rand.nextInt(45);
name = getRandomName(randName);
int nullNotNull = rand.nextInt(2);
switch (nullNotNull)
{
case 0:
field = null;
break;
case 1:
randField = rand.nextInt(24);
field = getRandomField(randField);
break;
}
testInsert(name, field);
break;
case 1:
id = rand.nextInt(Integer.parseInt(cursor.getString(0)));
//id = rand.nextInt(12)+1;
testDelete(id);
break;
case 2:
int selection = rand.nextInt(5);
switch (selection)
{
case 0:
randName = rand.nextInt(45);
id = rand.nextInt(Integer.parseInt(cursor.getString(0)));
//id = rand.nextInt(12)+1;
name = getRandomName(randName);
testUpdate(id, name, "");
break;
default:
randName = rand.nextInt(45);
name = getRandomName(randName);
randField = rand.nextInt(24);
field = getRandomField(randField);
id = rand.nextInt(Integer.parseInt(cursor.getString(0)));
//id = rand.nextInt(12)+1;
testUpdate(id, name, field);
break;
}
break;
case 3:
id = rand.nextInt(Integer.parseInt(cursor.getString(0)));
//id = rand.nextInt(12)+1;
testGet(id);
break;
case 4:
testGetAll();
break;
}
}
}
public class SQLTest extends Activity
{
public SQLAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqltest);
adapter = new SQLAdapter(this);
adapter.createDatabase();
open();
}
...
}
Well, thanks to Joel, I ended up creating a local database for the randomTest() method, which then called up the raw query:
This worked (although I then realized this wasn’t useful for the purposes of my project). Either way, if anyone else has a problem with using a cursor like this, this was the solution that worked for me.