В моем приложении есть база данных SQLite, которую я поместил в папку активов.Я успешно использую его в своем приложении, но теперь я хочу протестировать методы в классе «провайдера» базы данных, в котором есть несколько методов для операций CRUD.Я пытался выполнить этот урок https://medium.com/@elye.project/android-sqlite-database-unit-testing-is-easy-a09994701162, но мой тестовый класс не прошел, за исключением
android.database.sqlite.SQLiteException: Cannot open SQLite connection, base error code: 14
at org.robolectric.shadows.ShadowSQLiteConnection.rethrow(ShadowSQLiteConnection.java:56)
at org.robolectric.shadows.ShadowSQLiteConnection.access$500(ShadowSQLiteConnection.java:33)
at org.robolectric.shadows.ShadowSQLiteConnection$Connections.execute(ShadowSQLiteConnection.java:466)
at org.robolectric.shadows.ShadowSQLiteConnection$Connections.open(ShadowSQLiteConnection.java:353)
at org.robolectric.shadows.ShadowSQLiteConnection.nativeOpen(ShadowSQLiteConnection.java:61)
at android.database.sqlite.SQLiteConnection.nativeOpen(SQLiteConnection.java)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:806)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at com.education.frogtravel.ege4task.database.DBHelper.openDataBase(DBHelper.java:78)
at com.education.frogtravel.ege4task.database.DBProvider.<init>(DBProvider.kt:22)
at com.education.frogtravel.ege4task.database.DBProviderTest.setup(DBProviderTest.kt:23)
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.RunBefores.evaluate(RunBefores.java:24)
at org.robolectric.RobolectricTestRunner$2.evaluate(RobolectricTestRunner.java:251)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:188)
at org.robolectric.RobolectricTestRunner.runChild(RobolectricTestRunner.java:54)
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.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:152)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Caused by: com.almworks.sqlite4java.SQLiteException: [14] unable to open database file
at com.almworks.sqlite4java.SQLiteConnection.open0(SQLiteConnection.java:1353)
at com.almworks.sqlite4java.SQLiteConnection.open(SQLiteConnection.java:258)
at com.almworks.sqlite4java.SQLiteConnection.open(SQLiteConnection.java:269)
at org.robolectric.shadows.ShadowSQLiteConnection$Connections$1.call(ShadowSQLiteConnection.java:360)
at org.robolectric.shadows.ShadowSQLiteConnection$Connections$1.call(ShadowSQLiteConnection.java:353)
at org.robolectric.shadows.ShadowSQLiteConnection$Connections$6.call(ShadowSQLiteConnection.java:452)
at org.robolectric.shadows.ShadowSQLiteConnection$Connections$6.call(ShadowSQLiteConnection.java:446)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Он не прошел в методе
public void openDataBase() throws SQLException {
//Open the database
String myPath = DB_PATH + DBScheme.DB_NAME;
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
в соответствии с openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
Весь мой класс SQLiteOpenHelper
import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class DBHelper extends SQLiteOpenHelper {
private static String DB_PATH = "/data/data/my.package.path/databases/";
private SQLiteDatabase myDatabase;
private final Context context;
public DBHelper(Context context) {
super(context, DBScheme.DB_NAME, null, 1);
this.context = context;
}
public void createDatabase() throws IOException{
boolean dbExist = checkDataBase();
if(!dbExist){//If database doesn't exist
this.getReadableDatabase();
try{
copyDatabase();
}catch(IOException e){
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try{
String myPath = DB_PATH + DBScheme.DB_NAME;
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}catch (SQLiteException e){
//Database doesn't exist
}
return checkDB != null;
}
private void copyDatabase() throws IOException{
InputStream inputStream = context.getAssets().open(DBScheme.DB_NAME);
String outFileName = DB_PATH + DBScheme.DB_NAME;
OutputStream outputStream = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while((length = inputStream.read(buffer)) > 0){
outputStream.write(buffer, 0, length);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
public void openDataBase() throws SQLException {
//Open the database
String myPath = DB_PATH + DBScheme.DB_NAME;
myDatabase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}
@Override
public synchronized void close() {
if(myDatabase != null)
myDatabase.close();
super.close();
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
Мой класс тестирования
@RunWith(RobolectricGradleTestRunner::class)
@Config(constants = BuildConfig::class, sdk = intArrayOf(LOLLIPOP), packageName = "my.pachage.path.database")
class DBProviderTest {
lateinit var dbHelper: DBProvider
@Before
fun setup() {
dbHelper = DBProvider(RuntimeEnvironment.application)
dbHelper.clearStatistics()
}
//commented to test because crashed in this line before
// @After
// fun tearDown(){
// dbHelper.clearStatistics()
// }
@Test
fun testDBUpdate(){
dbHelper = DBProvider(RuntimeEnvironment.application)
val wordId = 1
val isRight = true
dbHelper.updateWordStatistics(wordId, isRight)
assertEquals(dbHelper.getStatisticsForWord(wordId), Statistics(wordId, 1, 1))
}
}
DBHelper находится на Java, а класс тестирования находится в Kotlin.Я думаю, это происходит потому, что я не делаю БД на ходу, а использую уже существующую.Я могу написать дополнительную логику для целей тестирования, но, как я понял, будет неправильно менять логику приложения только для тестирования.Итак, мой вопрос, как проверить БД, которая не создается, а просто открывается из папки ресурсов Android. \?