我试图在我的应用程序中实现一些测试。我想测试正在写一个Java对象到我的数据库,然后检索,并断言说出来的数据库对象的一件事是,在去的对象匹配运行JUnit测试的Android NPE
这里是我的MySQLiteHelper应用代码:
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.concurrent.atomic.AtomicInteger;
class MySQLiteHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "unittesttester.db";
private static final int DATABASE_VERSION = 8;
private static final String LOG_TAG = MySQLiteHelper.class.getSimpleName();
private static final int WEATHER_STALENESS_PERIOD_MS = 60 * 5 * 1000; //5 minutes
private AtomicInteger mOpenCounter = new AtomicInteger();
private static MySQLiteHelper mInstance = null;
private SQLiteDatabase db;
private Context mContext;
public static MySQLiteHelper getInstance(Context context) {
if (mInstance == null) {
mInstance = new MySQLiteHelper(context.getApplicationContext());
}
return mInstance;
}
private MySQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(WeatherTable.CREATE_TABLE_WEATHER);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (newVersion <= DATABASE_VERSION) {
onCreate(db);
}
}
private synchronized SQLiteDatabase openDatabase() {
final int i = mOpenCounter.incrementAndGet();
if (i == 1) {
db = getWritableDatabase();
}
return db;
}
private synchronized void closeDatabase() {
final int i = mOpenCounter.decrementAndGet();
if (i == 0) {
db.close();
}
}
private void truncateWeatherTable() {
db = openDatabase();
db.delete(WeatherTable.TABLE_WEATHER, null, null);
closeDatabase();
}
public void deleteAndInsertWeather(Weather weather) {
db = openDatabase();
db.beginTransaction();
try {
truncateWeatherTable();
insertWeather(weather);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
closeDatabase();
}
}
private void insertWeather(Weather weather) {
db = openDatabase();
db.insert(WeatherTable.TABLE_WEATHER, null, makeWeatherCv(weather));
closeDatabase();
}
public Weather getWeather() {
db = openDatabase();
String sql = "SELECT * FROM " + WeatherTable.TABLE_WEATHER;
Cursor c = null;
Weather weather = null;
try {
c = db.rawQuery(sql, null);
if (c.moveToFirst()) {
weather = makeWeather(c);
//If sample too old return null
if (System.currentTimeMillis() - weather.getTimestamp() > WEATHER_STALENESS_PERIOD_MS) {
weather = null;
truncateWeatherTable();
}
}
} finally {
if (c != null) {
c.close();
}
closeDatabase();
}
return weather;
}
private Weather makeWeather(Cursor c) {
Weather weather = new Weather();
weather.setTimestamp(c.getLong(c.getColumnIndex(WeatherTable.COLUMN_TIMESTAMP)));
weather.setElevation(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_ELEVATION)));
weather.setTemperature(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_TEMPERATURE)));
weather.setDusk(c.getInt(c.getColumnIndex(WeatherTable.COLUMN_DUSK)));
weather.setNighttime(c.getInt(c.getColumnIndex(WeatherTable.COLUMN_NIGHTTIME)));
weather.setGravity(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_GRAVITY)));
weather.setDaytime(c.getInt(c.getColumnIndex(WeatherTable.COLUMN_DAYTIME)));
weather.setHumidity(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_HUMIDITY)));
weather.setPressure(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_PRESSURE)));
weather.setOkta(c.getDouble(c.getColumnIndex(WeatherTable.COLUMN_OKTA)));
weather.setDawn(c.getInt(c.getColumnIndex(WeatherTable.COLUMN_DAWN)));
return weather;
}
private ContentValues makeWeatherCv(Weather weather) {
ContentValues contentValues = new ContentValues();
contentValues.put(WeatherTable.COLUMN_TIMESTAMP, weather.getTimestamp());
contentValues.put(WeatherTable.COLUMN_TEMPERATURE, weather.getElevation());
contentValues.put(WeatherTable.COLUMN_TEMPERATURE, weather.getTemperature());
contentValues.put(WeatherTable.COLUMN_DUSK, weather.getDusk());
contentValues.put(WeatherTable.COLUMN_NIGHTTIME, weather.getNighttime());
contentValues.put(WeatherTable.COLUMN_GRAVITY, weather.getGravity());
contentValues.put(WeatherTable.COLUMN_DAYTIME, weather.getDaytime());
contentValues.put(WeatherTable.COLUMN_HUMIDITY, weather.getHumidity());
contentValues.put(WeatherTable.COLUMN_PRESSURE, weather.getPressure());
contentValues.put(WeatherTable.COLUMN_OKTA, weather.getOkta());
contentValues.put(WeatherTable.COLUMN_DAWN, weather.getDawn());
return contentValues;
}
}
这是我对上面的类测试类:
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
import org.junit.Test;
import static org.mockito.Mockito.*;
public class MySQLiteHelperTest extends AndroidTestCase {
private MySQLiteHelper db;
private Weather mockedWeather = mock(Weather.class);
@Override
public void setUp() throws Exception {
super.setUp();
context = new MockContext();
setContext(context);
assertNotNull(context);
RenamingDelegatingContext renamingContext = new RenamingDelegatingContext(getContext(), "test_");
db = MySQLiteHelper.getInstance(renamingContext);
assertNotNull(db);
when(mockedWeather.getDawn()).thenReturn(0);
when(mockedWeather.getDaytime()).thenReturn(1);
when(mockedWeather.getDusk()).thenReturn(2);
when(mockedWeather.getElevation()).thenReturn(3.0);
when(mockedWeather.getGravity()).thenReturn(4.0);
when(mockedWeather.getHumidity()).thenReturn(5.0);
when(mockedWeather.getNighttime()).thenReturn(6);
when(mockedWeather.getOkta()).thenReturn(7.0);
when(mockedWeather.getPressure()).thenReturn(8.0);
when(mockedWeather.getTemperature()).thenReturn(9.0);
when(mockedWeather.getTimestamp()).thenReturn(10L);
}
@Override
public void tearDown() throws Exception {
super.tearDown();
}
public void testGetInstance() throws Exception {
}
public void testOnCreate() throws Exception {
}
public void testOnUpgrade() throws Exception {
}
@Test
public void testDeleteAndInsertWeather() throws Exception {
db.deleteAndInsertWeather(mockedWeather);
Weather actualWeather = db.getWeather();
assertEquals(mockedWeather.getDawn(), actualWeather.getDawn());
assertEquals(mockedWeather.getDaytime(), actualWeather.getDaytime());
assertEquals(mockedWeather.getDusk(), actualWeather.getDusk());
assertEquals(mockedWeather.getElevation(), actualWeather.getElevation());
assertEquals(mockedWeather.getGravity(), actualWeather.getGravity());
assertEquals(mockedWeather.getHumidity(), actualWeather.getHumidity());
assertEquals(mockedWeather.getNighttime(), actualWeather.getNighttime());
assertEquals(mockedWeather.getOkta(), actualWeather.getOkta());
assertEquals(mockedWeather.getPressure(), actualWeather.getPressure());
assertEquals(mockedWeather.getTemperature(), actualWeather.getTemperature());
assertEquals(mockedWeather.getTimestamp(), actualWeather.getTimestamp());
}
public void testDeleteWeather() throws Exception {
}
public void testInsertWeather() throws Exception {
}
public void testGetWeather() throws Exception {
}
public void testWeatherMakeCv() throws Exception {
}
}
当我运行测试我的测试过程中,我得到一个NPE。这似乎发生在MySQLiteHelper类具有其db = getWritableDatabase()行时。 getWriteableDatabase()是来自基类的公共方法。
我不认为我明白为什么这个测试会导致NPE。在我的测试中,我调用了应该初始化类的静态方法MySQLiteHelper.getInstance(Context context)。我的假设是调用getInstance将为我提供一个完全初始化的MySQLiteHelper实例。为什么这似乎没有发生?
编辑: 我现在的问题是,当getWritableDatabase()被调用时返回NULL而不是SQLiteDatabase的实例。
你为什么使用'context.getApplicationContext()'?不应该'上下文'只够? –
删除getApplicationContext()并再次测试导致相同的行为。 – neonDion
@MeghVidani context.getApplicationContext()确实返回null,所以你是正确的,这是问题之一。但是,在删除getApplicationContext()部分后,我仍然遇到问题。 – neonDion