我正在尝试在我自己的项目中设置roboelectric和fest。但是,当我尝试在命令行中运行./gradlew clean test时,我在测试报告中收到以下错误:
我的项目确实构建了应用程序而没有错误。我只是在尝试运行测试时才遇到这个问题,所以Roboelectric似乎并不知道我的原生sqlcipher二进制文件和其他二进制文件。
所以我尝试用加载必要二进制文件的运行器的阴影类加载它:
@Config(emulateSdk = 18, shadows={MyJniClass.class})
@RunWith(RobolectricTestRunner.class)
public class MainActivityBuildTest {
@Test
public void testSomething() throws Exception {
Activity activity = Robolectric.buildActivity(MainActivity.class).create().get();
assertTrue(activity != null);
}
}
使用我的自定义jniloader阴影类
@Implements(RobolectricTestRunner.class)
class MyJniClass {
static {
try {
System.loadLibrary("libdatabase_sqlcipher");
System.loadLibrary("libdatabase_android");
System.loadLibrary("libstlport_shared");
} catch (UnsatisfiedLinkError e) {
// only ignore exception in non-android env
if ("Dalvik".equals(System.getProperty("java.vm.name"))) throw e;
}
}
}
答案 0 :(得分:2)
使用sbo密码与robolectric有问题吗?
我的解决方法是使用两个不同的SQLiteOpenHelper实现。一个使用sqlcipher,另一个使用默认数据库实现。这两者都在工厂类后面,它根据静态布尔标志创建SQLiteDatabase,因此将从progard中消除不安全的数据库处理。
下一个问题是两者都有不同的SQLiteDatabase类。因此,再次围绕SQLiteDatabase构建一个包装器,它将使用SQLiteOpenHelper Wrapper中正确的SQLiteDatabase创建。以Cipher变体为基础。您可以忽略默认SQLiteDatabase中存在但不存在密码变体的方法。此包装类使用相同的静态布尔标志来选择应使用的数据库。如果出错并采取错误的数据库,那么它应该抛出一个空指针异常;)
在您的应用代码中,您现在应该只使用包装类。
DatabaseHelper包装器的示例
public class MyDatabaseHelper {
public static final String DATABASE_NAME = "my.db";
public static final int DATABASE_VERSION = 1;
MyEncryptedDatabaseHelper encryptedDatabase;
MyUnsecureDatabaseHelper unsecureDatabase;
public MyDatabaseHelper(Context context) {
if (ReleaseControl.USE_UNSECURE_DATABASE) {
unsecureDatabase = new MyUnsecureDatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
return;
}
encryptedDatabase = new MyEncryptedDatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
}
public MySQLiteDatabase getWritableDatabase(String password) throws MySQLiteException {
if (ReleaseControl.USE_UNSECURE_DATABASE) {
try {
return new MySQLiteDatabase(unsecureDatabase.getWritableDatabase());
} catch (android.database.SQLException e) {
throw new MySQLiteException(e);
}
}
try {
return new MySQLiteDatabase(encryptedDatabase.getWritableDatabase(password));
} catch (net.sqlcipher.database.SQLiteException e) {
throw new MySQLiteException(e);
}
}
}
来自SQLiteDatabase包装器的和简短片段
public class MySQLiteDatabase {
private net.sqlcipher.database.SQLiteDatabase encryptedDatabase;
private android.database.sqlite.SQLiteDatabase unsecureDatabase;
public MySQLiteDatabase(SQLiteDatabase database) {
encryptedDatabase = database;
}
public MySQLiteDatabase(android.database.sqlite.SQLiteDatabase database) {
unsecureDatabase = database;
}
public static void loadLibs(android.content.Context context) {
if (ReleaseControl.USE_UNSECURE_DATABASE) { return; }
SQLiteDatabase.loadLibs(context);
}
public static int releaseMemory() {
if (ReleaseControl.USE_UNSECURE_DATABASE) {
return android.database.sqlite.SQLiteDatabase.releaseMemory();
}
return net.sqlcipher.database.SQLiteDatabase.releaseMemory();
}
public static SQLiteDatabase openDatabase(String path, String password, MyCursorFactory factory, int flags) {
if(factory == null) factory = new NullCursorFactory();
if (ReleaseControl.USE_UNSECURE_DATABASE) {
return new MySQLiteDatabase(android.database.sqlite.SQLiteDatabase.openDatabase(path, factory.getUnsecure(), flags));
}
return new MySQLiteDatabase(net.sqlcipher.database.SQLiteDatabase.openDatabase(path, password, factory.getEncrypted(), flags));
}
在robolectric测试中,我将每次反射的USE_UNSECURE_DATABASE设置为真