Android 测试 = 打开已经关闭的数据库

标签 android sqlite testing

我制作了一个应用程序,它复制一个预制的数据库,然后允许您以 SQLTest 为主要 Activity 运行 SQLiteDatabase 的各种查询/方法(插入、更新等)。然后我做了一个测试(称为 SQLTestCase,我知道它不合适,但我是测试新手),它有一个测试套件调用随机选择要执行的测试的 randomTest() 方法。奇怪的是我收到一条错误消息:

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)

错误出现在两行代码中:

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
            ...

我知道问题出在游标的初始化上,因为通过注释掉它,测试运行正常。有人知道这个问题吗?我查看了我的代码,希望找到一个我提前关闭数据库的地方,但我什么也没看到。我会尽力提供你所需要的。让我知道是否需要更多代码来解决此问题。

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

最佳答案

好吧,感谢 Joel,我最终为 randomTest() 方法创建了一个本地数据库,然后它调用了原始查询:

String sql = "SELECT COUNT(*) AS NumberOfRecords FROM " + SQLAdapter.TABLE_OS;
SQLiteDatabase db = activity.accessAdapter().accessHelper().getWritableDatabase();
Cursor cursor = db.rawQuery(sql, null);

这行得通(尽管我后来意识到这对我的项目没有用)。无论哪种方式,如果其他人在使用这样的游标时遇到问题,这就是对我有用的解决方案。

关于Android 测试 = 打开已经关闭的数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11616106/

相关文章:

Android Studio 返回错误 "Unable to resolve superclass"

sqlite - 如何在 SQlite 中获取当前日期时间格式?

c# - 在 SQLite 中为 WinRT 实现自定义排序规则

java - 服务和电信要求

oracle - PL/SQL 的单元测试

android - 如何在AChartEngine中为CombinedXYChart设置X轴的日期格式

android - 使用 LocationListener 每 100 米更新一次位置

android - 开始使用 JUCE for Android

sqlite - 限制 sqlite3 中的浮点值

java - Junit 测试在 Eclipse 中运行但失败并显示 `gradle test`