使用Robolectric和ORMLite进行测试时使用mock db

时间:2015-02-17 14:35:41

标签: android sqlite gradle ormlite robolectric

我正在使用 OrmLiteSqliteOpenHelper 连接到SQLite数据库的Android应用。

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;
    }
}

要从数据库中获取数据,我有一些提供程序类,它们使用一些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类,我应该这样做:

@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应用程序的标准位置使用db,而不是我的本地文件。 如何修改我的测试代码,使用添加为资产资源的本地数据库进行测试,而无需触及应用程序的真实代码?

2 个答案:

答案 0 :(得分:1)

对于那些无法忍受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密集的套件,每次在GenyMotion上刷2.5秒。

如果您还没有及时了解它,我绝对建议您查看Google最近对其测试功能所做的工作。 The intro on the Robolectric site在这一点上是一个平坦的谎言。

答案 1 :(得分:0)

我们是如何做到的。

  1. 我们将示例数据库文件放在src/test/res文件夹
  2. 我们在DB测试之前运行下一个代码:

    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 ) );
    } 
    
  3. 小心,因为这些测试超长