测试TestDb时会产生创建表的错误

时间:2016-02-22 09:42:15

标签: android sqlite android-sqlite

我想从sqlite数据库中的网站保存数据

WeatheDbHelper.java

         /*sqlite database handler*/


         package com.example.admin.sunshine.app.data;

         import android.content.Context;
          import android.database.sqlite.SQLiteDatabase;
          import android.database.sqlite.SQLiteOpenHelper;

        /**
     * Created by admin on 18/02/2016.
     */
    public class WeatherDbHelper extends SQLiteOpenHelper{

        private static final int DATABASE_VERSION=2;
        static final String DATABASE_NAME="weather.db";

        public WeatherDbHelper(Context context)
        {
            super(context,DATABASE_NAME,null,DATABASE_VERSION);
        }

    @Override
        public void onCreate(SQLiteDatabase sqLiteDatabase)
        {
           final String SQL_CREATE_LOCATION_TABLE="CREATE TABLE"+ WeatherContract.LocationEntry.TABLE_NAME+"("+
                   WeatherContract.LocationEntry._ID+"INTEGER PRIMARY KEY,"+
                   WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING+"TEXT UNIQUE NOT NULL,"+
                   WeatherContract.LocationEntry.COLUMN_CITY_NAME+"TEXT NOT NULL,"+
                   WeatherContract.LocationEntry.COLUMN_COORD_LAT+"REAL NOT NULL,"+
                   WeatherContract.LocationEntry.COLUMN_COORD_LONG+"REAL NOT NULL"+
                   ");";



            final String SQL_CREATE_WEATHER_TABLE="CREATE TABLE" + WeatherContract.WeatherEntry.TABLE_NAME+"("+
                    WeatherContract.WeatherEntry._ID +"INTEGER PRIMARY KEY AUTOINCREMENT,"+
                    WeatherContract.WeatherEntry.COLUMN_LOC_KEY +"INTEGER NOT NULL,"+
                    WeatherContract.WeatherEntry.COLUMN_DATE +"INTEGER NOT NULL,"+
                    WeatherContract.WeatherEntry.COLUMN_SHORT_DESC +"TEXT NOT NULL,"+
                    WeatherContract.WeatherEntry.COLUMN_WEATHER_ID +"INTEGER NOT NULL,"+
                    WeatherContract.WeatherEntry.COLUMN_MIN_TEMP +"REAL NOT NULL,"+
                    WeatherContract.WeatherEntry.COLUMN_MAX_TEMP +"REAL NOT NULL,"+
                    WeatherContract.WeatherEntry.COLUMN_HUMIDITY +"REAL NOT NULL,"+
                    WeatherContract.WeatherEntry.COLUMN_PRESSURE +"REAL NOT NULL,"+
                    WeatherContract.WeatherEntry.COLUMN_WIND_SPEED +"REAL NOT NULL,"+
                    WeatherContract.WeatherEntry.COLUMN_DEGREES +"REAL NOT NULL,"+
                    "FOREIGN KEY("+ WeatherContract.WeatherEntry.COLUMN_LOC_KEY +")REFERENCES "+
                    WeatherContract.LocationEntry.TABLE_NAME +"("+ WeatherContract.LocationEntry._ID+"),"+
                    "UNIQUE ("+ WeatherContract.WeatherEntry.COLUMN_DATE+","+ WeatherContract.WeatherEntry.COLUMN_LOC_KEY+
                    ") ON CONFLICT REPLACE);";

            sqLiteDatabase.execSQL(SQL_CREATE_WEATHER_TABLE);
        }
        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase,int oldVersion, int newVersion)
        {
            sqLiteDatabase.execSQL("DROP TABLE IF EXIST"+ WeatherContract.LocationEntry.TABLE_NAME);
            sqLiteDatabase.execSQL("DROP TABLE IF EXIST"+ WeatherContract.WeatherEntry.TABLE_NAME);
            onCreate(sqLiteDatabase);
        }

    }      

TestDb.java用于测试create table

    /*creating the SQLite database

    package com.example.admin.sunshine.app.data;

    /**
     * Created by admin on 22/02/2016.
     */
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.test.AndroidTestCase;

    import java.util.HashSet;

    public class TestDb extends AndroidTestCase {

        public static final String LOG_TAG = TestDb.class.getSimpleName();

        // Since we want each test to start with a clean slate
        void deleteTheDatabase() {
            mContext.deleteDatabase(WeatherDbHelper.DATABASE_NAME);
        }

        /*
            This function gets called before each test is executed to delete the database.  This makes
            sure that we always have a clean test.
         */
        public void setUp() {
            deleteTheDatabase();
        }

        /*
            Students: Uncomment this test once you've written the code to create the Location
            table.  Note that you will have to have chosen the same column names that I did in
            my solution for this test to compile, so if you haven't yet done that, this is
            a good time to change your column names to match mine.
            Note that this only tests that the Location table has the correct columns, since we
            give you the code for the weather table.  This test does not look at the
         */
        public void testCreateDb() throws Throwable {
            // build a HashSet of all of the table names we wish to look for
            // Note that there will be another table in the DB that stores the
            // Android metadata (db version information)
            final HashSet<String> tableNameHashSet = new HashSet<String>();
            tableNameHashSet.add(WeatherContract.LocationEntry.TABLE_NAME);
            tableNameHashSet.add(WeatherContract.WeatherEntry.TABLE_NAME);

            boolean b = mContext.deleteDatabase(WeatherDbHelper.DATABASE_NAME);
            SQLiteDatabase db = new WeatherDbHelper(
                    this.mContext).getWritableDatabase();
            assertEquals(true, db.isOpen());

            // have we created the tables we want?
            Cursor c = db.rawQuery("SELECT name FROM sqlite_master WHERE type='table'", null);

            assertTrue("Error: This means that the database has not been created correctly",
                    c.moveToFirst());

            // verify that the tables have been created
            do {
                tableNameHashSet.remove(c.getString(0));
            } while( c.moveToNext() );

            // if this fails, it means that your database doesn't contain both the location entry
            // and weather entry tables
            assertTrue("Error: Your database was created without both the location entry and weather entry tables",
                    tableNameHashSet.isEmpty());

            // now, do our tables contain the correct columns?
            c = db.rawQuery("PRAGMA table_info(" + WeatherContract.LocationEntry.TABLE_NAME + ")",
                    null);

            assertTrue("Error: This means that we were unable to query the database for table information.",
                    c.moveToFirst());

            // Build a HashSet of all of the column names we want to look for
            final HashSet<String> locationColumnHashSet = new HashSet<String>();
            locationColumnHashSet.add(WeatherContract.LocationEntry._ID);
            locationColumnHashSet.add(WeatherContract.LocationEntry.COLUMN_CITY_NAME);
            locationColumnHashSet.add(WeatherContract.LocationEntry.COLUMN_COORD_LAT);
            locationColumnHashSet.add(WeatherContract.LocationEntry.COLUMN_COORD_LONG);
            locationColumnHashSet.add(WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING);

            int columnNameIndex = c.getColumnIndex("name");
            do {
                String columnName = c.getString(columnNameIndex);
                locationColumnHashSet.remove(columnName);
            } while(c.moveToNext());

            // if this fails, it means that your database doesn't contain all of the required location
            // entry columns
            assertTrue("Error: The database doesn't contain all of the required location entry columns",
                    locationColumnHashSet.isEmpty());
            db.close();
        }

        /*
            Students:  Here is where you will build code to test that we can insert and query the
            location database.  We've done a lot of work for you.  You'll want to look in TestUtilities
            where you can uncomment out the "createNorthPoleLocationValues" function.  You can
            also make use of the ValidateCurrentRecord function from within TestUtilities.
        */
        public void testLocationTable() {
            String testLocationSetting = "99705";
            String testCityName = "North Pole";
            double testLatitude = 64.7488;
            double testLongitude = -147.353;
            // First step: Get reference to writable database
            SQLiteDatabase db = new WeatherDbHelper(
                    this.mContext).getWritableDatabase();
            assertEquals(true, db.isOpen());
            // Create ContentValues of what you want to insert
            // (you can use the createNorthPoleLocationValues if you wish)
            ContentValues locationValues = new ContentValues();
            locationValues.put(WeatherContract.LocationEntry.COLUMN_LOCATION_SETTING, testLocationSetting);
            locationValues.put(WeatherContract.LocationEntry.COLUMN_CITY_NAME, testCityName);
            locationValues.put(WeatherContract.LocationEntry.COLUMN_COORD_LAT, testLatitude);
            locationValues.put(WeatherContract.LocationEntry.COLUMN_COORD_LONG, testLongitude);

            // Insert ContentValues into database and get a row ID back
            long locationRowId;
            locationRowId = db.insert(WeatherContract.LocationEntry.TABLE_NAME, null, locationValues);
            assertTrue(locationRowId != -1);
            // Query the database and receive a Cursor back
            Cursor c = db.query(WeatherContract.LocationEntry.TABLE_NAME,
                    null, //all columns
                    null, //columns for the "where" clause
                    null, //values fro the "where" clause
                    null, //columns to group by
                    null, //columns to filter by row groups
                    null  //sort order
            );
            // Move the cursor to a valid database row
            assertTrue(" Error: No Records returned from location query", c.moveToFirst());
            // Validate data in resulting Cursor with the original ContentValues
            // (you can use the validateCurrentRecord function in TestUtilities to validate the
            // query if you like)
            TestUtilities.validateCurrentRecord("Error: location query validation failed", c, locationValues);

            //Move the cursor to demonstrate that there is only one record in the database
            assertFalse("Error: More than one record returned from location query", c.moveToNext());
            // Finally, close the cursor and database
            c.close();
            db.close();

        }

        /*
            Students:  Here is where you will build code to test that we can insert and query the
            database.  We've done a lot of work for you.  You'll want to look in TestUtilities
            where you can use the "createWeatherValues" function.  You can
            also make use of the validateCurrentRecord function from within TestUtilities.
         */
        public void testWeatherTable() {
            // First insert the location, and then use the locationRowId to insert
            // the weather. Make sure to cover as many failure cases as you can.
            long locationRowId = TestUtilities.insertNorthPoleLocationValues(mContext);
            // Make sure we have a valid row ID.
            assertFalse("Error: Location Not Inserted Correctly", locationRowId == -1L);
            // Instead of rewriting all of the code we've already written in testLocationTable
            // we can move this code to insertLocation and then call insertLocation from both
            // tests. Why move it? We need the code to return the ID of the inserted location
            // and our testLocationTable can only return void because it's a test.

            // First step: Get reference to writable database
            SQLiteDatabase db = new WeatherDbHelper(this.mContext)
                    .getWritableDatabase();
            // Create ContentValues of what you want to insert
            // (you can use the createWeatherValues TestUtilities function if you wish)
            ContentValues contentValues = TestUtilities.createWeatherValues(locationRowId);
            // Insert ContentValues into database and get a row ID back
            long weatherRowId =  db.insert(WeatherContract.WeatherEntry.TABLE_NAME, null, contentValues);
            assertTrue(weatherRowId != -1);
            // Query the database and receive a Cursor back
            Cursor cursor = db.query(WeatherContract.WeatherEntry.TABLE_NAME,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null
            );
            // Move the cursor to a valid database row
            assertTrue("Error: No Records Returned from Weather Query", cursor.moveToFirst());
            // Validate data in resulting Cursor with the original ContentValues
            // (you can use the validateCurrentRecord function in TestUtilities to validate the
            // query if you like)
            TestUtilities.validateCurrentRecord("Error: weather query validation failed", cursor, contentValues);
            // Move the cursor to demonstrate that there is only one record in the database
            assertFalse( "Error: More than one record returned from weather query",
                    cursor.moveToNext() );
            // Finally, close the cursor and database
            cursor.close();
            db.close();
        }


        /*
            Students: This is a helper method for the testWeatherTable quiz. You can move your
            code from testLocationTable to here so that you can call this code from both
            testWeatherTable and testLocationTable.
         */
        public long insertLocation() {
            return -1L;
        }
    }

以下是在AndroidTest中测试TestDb时的错误

logcat的:

 android.database.sqlite.SQLiteException: near "TABLEweather": syntax error (code 1): , while compiling: CREATE TABLEweather(_idINTEGER PRIMARY KEY AUTOINCREMENT,location_idINTEGER NOT NULL,dateINTEGER NOT NULL,short_descTEXT NOT NULL,weather_idINTEGER NOT NULL,minREAL NOT NULL,maxREAL NOT NULL,humidityREAL NOT NULL,pressureREAL NOT NULL,windREAL NOT NULL,degreesREAL NOT NULL,FOREIGN KEY(location_id)REFERENCES location(_id),UNIQUE (date,location_id) ON CONFLICT REPLACE);
    at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
    at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
    at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
    at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
    at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
    at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1674)
    at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605)
    at com.example.admin.sunshine.app.data.WeatherDbHelper.onCreate(WeatherDbHelper.java:50)
    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:251)
    at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
    at com.example.admin.sunshine.app.data.TestUtilities.insertNorthPoleLocationValues(TestUtilities.java:90)
    at com.example.admin.sunshine.app.data.TestDb.testWeatherTable(TestDb.java:155)
    at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
    at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
    at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837)

1 个答案:

答案 0 :(得分:1)

你需要在你的Create表脚本中放置一些“空格”,特别是在你打开/关闭双引号(“)的地方。下面我试着在每个双引号中放一个空格,你可以检查它是否正常或者我错过了什么。

map<int,string> mymap;
int mymax = 100;

for(int key=0;key<=mymax;++key)//creates a map with 101 keys from 0-100
 mymap[key] = "somestring";

//to check do the following
for(int key=0;key<=mymax;++key)
 std::cout<<mymap[key]<<std::endl;