我正在尝试为Android开发人员中的SQLite数据库编写一个单元测试。但是,当我运行测试课时,我会收到以下错误:
java.lang.RuntimeException: Method getWritableDatabase in android.database.sqlite.SQLiteOpenHelper not mocked. See http://g.co/androidstudio/not-mocked for details.
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java)
at com.example.jack.app4.helper.CharityHelper.insertData(CharityHelper.java:54)
at helper.TestCharityHelper.testInsertAndSelectAll(TestCharityHelper.java:63)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
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.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:262)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
问题在于,我在测试开始时创建的CharityHelper实例是无效的,但是我无法确定如何解决此问题。任何帮助将不胜感激。
我的访问类要测试:
/**
* Accessor class for Charity Table.
*
* Created by Jack on 07/09/2017.
*/
public class CharityHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "Example.db";
private static final String TABLE_NAME = "Charity";
private static final String ID = "id";
private static final String CHARITY_NAME = "charityName";
private static final String CHARITY_NUMBER = "charityNumber";
private static final String POSTCODE= "postCode";
private static final String CHARITY_TYPE= "charityType";
public CharityHelper(Context context) {
super(context, DATABASE_NAME, null , 1);
// SQLiteDatabase db = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, CHARITY_NAME TEXT, CHARITY_NUMBER INTEGER, POSTCODE VARCHAR, GENRE VARCHAR)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int i, int i1) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
/**
* Insert record into charity table.
* @param charity - charity to be inserted
* @return boolean - whether insert was successful or not.
*/
public boolean insertData(Charity charity) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(CHARITY_NAME, charity.getName());
contentValues.put(CHARITY_NUMBER, charity.getNumber());
contentValues.put(POSTCODE, charity.getPostcode());
contentValues.put(CHARITY_TYPE, charity.getCharityType().toString());
long result = db.insert(TABLE_NAME, null, contentValues);
return result != -1;
}
/**
* Method to return list of all charities in db.
* Will return empty list if no record found.
* @return List<Charity>
*/
public List<Charity> selectAll() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
return getCharitiesListFromCursor(cursor);
}
/**
* Method to return list of all charities in db of the charity type passed in.
* Will return empty list if no record found.
* @return List<Charity>
*/
public List<Charity> selectByCharityType(Charity.CharityType charityType) {
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME + " WHERE genre = ?", new String[] {charityType.toString()});
return getCharitiesListFromCursor(cursor);
}
/**
* Takes cursor from db query and convert into list of charities.
* @param cursor - passed in cursor
* @return List Charity
*/
private List<Charity> getCharitiesListFromCursor(Cursor cursor) {
List<Charity> charityList = new ArrayList<>();
while (cursor.moveToNext()) {
charityList.add(new Charity(
cursor.getString(cursor.getColumnIndex(CHARITY_NAME)),
cursor.getLong(cursor.getColumnIndex(CHARITY_NUMBER)),
cursor.getString(cursor.getColumnIndex(POSTCODE)),
Charity.CharityType.valueOf(cursor.getString(cursor.getColumnIndex(CHARITY_TYPE)))
));
}
return charityList;
}
}
我的测试课:
/**
* Test class for Charity Helper
* Created by Jack on 10/09/2017.
*/
@RunWith(MockitoJUnitRunner.class)
public class TestCharityHelper {
private Charity testCharity;
private CharityHelper charityHelper;
private final String testCharityName = "testName";
private final Long testCharityNumber = 1234L;
private final String testCharityPostcode = "CO10 8NP";
private final Charity.CharityType testCharityType = Charity.CharityType.ANIMAL;
@Mock
SQLiteDatabase dbMock;
@Mock Context mockContext;
@Before
public void onSetup() {
charityHelper = new CharityHelper(mockContext);
testCharity = new Charity(testCharityName,testCharityNumber,testCharityPostcode,testCharityType);
}
@After
public void tearDown() throws Exception{
charityHelper.close();
// super.tearDown();
}
@Test
public void testInsertAndSelectAll() {
charityHelper.insertData(testCharity);
List<Charity> returnedCharityList = charityHelper.selectAll();
assertTrue(returnedCharityList.contains(testCharity));
}
}
在您的设置方法中,您需要使用RenamingDelegatingContext()方法返回的上下文。您还需要扩展AndroidTestcase类
public class TestCharityHelper extends AndroidTestCase{
.
.
private RenamingDelegatingContext mockContext;
public void setUp() throws Exception {
super.setUp();
final String prefix = "test";
mockContext = new RenamingDelegatingContext(getContext(),prefix);
charityHelper = new CharityHelper(mockContext);
testCharity = new Charity(testCharityName,testCharityNumber,testCharityPostcode,testCharityType);
}