使用 Robolectric 和 ORMLite 进行测试时使用模拟数据库
Use mock db when testing with Robolectric and ORMLite
我正在开发一个 Android 应用程序,它使用 OrmLiteSqliteOpenHelper 连接到 SQLite 数据库。
public class MyDatabaseHelper extends OrmLiteSqliteOpenHelper {
...
private static final String DATABASE_NAME = "mydb.sqlite";
private static MyDatabaseHelper helper = null;
private MyDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, BuildConfig.DATABASE_VERSION);
}
public static synchronized MyDatabaseHelper getHelper(Context context) {
if (helper == null) {
helper = new MyDatabaseHelper(context);
}
return helper;
}
}
为了从数据库获取数据,我有一些提供程序 classes,他们使用一些 DAO。
public class ProductsProvider {
public static List<Products> getProducts(Context context) {
MyDatabaseHelper helper = MyDatabaseHelper.getHelper(context);
Dao<Product, String> daoProducts = helperDatabase.getProductDao();
...
...
...
}
}
我已经准备好 Robolectric 来测试我的代码,但我很难理解如何 Robolectric 与 ORMLite 一起使用。
我的想法是有一个模拟 database.sqlite,预先填充我通常拥有的相同结构和数据,并将其用于我的所有测试。例如,如果我想测试 ProductsProvider class,我应该这样做:
@RunWith(MyTestRunner.class)
public class ProductsProviderTest extends MyTestCase {
@Test
public void testDb() {
List<Products> products = ProductsProvider.getProducts(getTestContext());
assertNotNull(products);
assertFalse(products.isEmpty());
}
}
请注意 ProductsProvider.getProducts() 将使用 MyDatabaseHelper,它将使用 Android 应用程序标准位置的数据库,而不是我的本地文件。
如何修改我的测试代码以使用本地数据库作为 asset 或 resource 添加测试,而不触及真正的代码应用程序?
这是我们的做法。
- 我们将示例数据库文件放在
src/test/res
文件夹中
我们运行数据库测试前的下一个代码:
private void copyTestDatabase( String resourceDBName )
throws URISyntaxException, IOException
{
String filePath = getClass().getResource( resourceDBName ).toURI().getPath();
String destinationPath = new ContextWrapper( Robolectric.application.getApplicationContext() ).getDatabasePath(
DatabaseHelper.DATABASE_NAME ).getAbsolutePath();
Files.copy( new File( filePath ), new File( destinationPath ) );
}
要小心,因为这些测试超长
对于无法忍受 Robolectric 3 + Gradle 的 6-12 秒启动时间的任何人,以下适用于 Android 的内置 JUnit4 测试(DbHelper
扩展 OrmLiteSqliteOpenHelper
)。
@RunWith(AndroidJUnit4.class)
public class DbTest {
private DbHelper dbHelper;
@Before
public void setUp() throws Exception {
Context context = new RenamingDelegatingContext(
InstrumentationRegistry.getTargetContext(), "test_");
dbHelper = new DbHelper(context);
}
}
您可能可以进行许多优化,但我可以 运行 一个小的 I/O-heavy 套件,每次在 GenyMotion 上擦除数据库只需 2.5 秒。
如果您还没有跟上它的最新动态,我强烈建议您查看 Google 最近对其测试功能所做的工作。 The intro on the Robolectric site 在这一点上是一个彻头彻尾的谎言。
我正在开发一个 Android 应用程序,它使用 OrmLiteSqliteOpenHelper 连接到 SQLite 数据库。
public class MyDatabaseHelper extends OrmLiteSqliteOpenHelper {
...
private static final String DATABASE_NAME = "mydb.sqlite";
private static MyDatabaseHelper helper = null;
private MyDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, BuildConfig.DATABASE_VERSION);
}
public static synchronized MyDatabaseHelper getHelper(Context context) {
if (helper == null) {
helper = new MyDatabaseHelper(context);
}
return helper;
}
}
为了从数据库获取数据,我有一些提供程序 classes,他们使用一些 DAO。
public class ProductsProvider {
public static List<Products> getProducts(Context context) {
MyDatabaseHelper helper = MyDatabaseHelper.getHelper(context);
Dao<Product, String> daoProducts = helperDatabase.getProductDao();
...
...
...
}
}
我已经准备好 Robolectric 来测试我的代码,但我很难理解如何 Robolectric 与 ORMLite 一起使用。 我的想法是有一个模拟 database.sqlite,预先填充我通常拥有的相同结构和数据,并将其用于我的所有测试。例如,如果我想测试 ProductsProvider class,我应该这样做:
@RunWith(MyTestRunner.class)
public class ProductsProviderTest extends MyTestCase {
@Test
public void testDb() {
List<Products> products = ProductsProvider.getProducts(getTestContext());
assertNotNull(products);
assertFalse(products.isEmpty());
}
}
请注意 ProductsProvider.getProducts() 将使用 MyDatabaseHelper,它将使用 Android 应用程序标准位置的数据库,而不是我的本地文件。 如何修改我的测试代码以使用本地数据库作为 asset 或 resource 添加测试,而不触及真正的代码应用程序?
这是我们的做法。
- 我们将示例数据库文件放在
src/test/res
文件夹中 我们运行数据库测试前的下一个代码:
private void copyTestDatabase( String resourceDBName ) throws URISyntaxException, IOException { String filePath = getClass().getResource( resourceDBName ).toURI().getPath(); String destinationPath = new ContextWrapper( Robolectric.application.getApplicationContext() ).getDatabasePath( DatabaseHelper.DATABASE_NAME ).getAbsolutePath(); Files.copy( new File( filePath ), new File( destinationPath ) ); }
要小心,因为这些测试超长
对于无法忍受 Robolectric 3 + Gradle 的 6-12 秒启动时间的任何人,以下适用于 Android 的内置 JUnit4 测试(DbHelper
扩展 OrmLiteSqliteOpenHelper
)。
@RunWith(AndroidJUnit4.class)
public class DbTest {
private DbHelper dbHelper;
@Before
public void setUp() throws Exception {
Context context = new RenamingDelegatingContext(
InstrumentationRegistry.getTargetContext(), "test_");
dbHelper = new DbHelper(context);
}
}
您可能可以进行许多优化,但我可以 运行 一个小的 I/O-heavy 套件,每次在 GenyMotion 上擦除数据库只需 2.5 秒。
如果您还没有跟上它的最新动态,我强烈建议您查看 Google 最近对其测试功能所做的工作。 The intro on the Robolectric site 在这一点上是一个彻头彻尾的谎言。