Testing Room Databases: On-Device vs. Local JVM

Test your Room database in two ways: on an Android device for realism, or on your local JVM for speed. This is crucial for verifying DAO queries and preventing data bugs. The footgun is assuming local tests behave identically to on-device tests.
WHY IT EXISTS: Automated database testing exists to verify your data persistence logic—the SQL inside your Data Access Objects (DAOs)—without manually running the app. It prevents regressions, ensuring that changes to queries or your database schema don't corrupt user data or break the app.
THE MENTAL MODEL: Think of testing Room as choosing your battleground. You can run tests on an actual Android device or emulator (an instrumented test), which is slow but perfectly realistic. Or, you can run them on your development machine's JVM (a local unit test), which is blazing fast but requires simulating the Android environment, introducing potential inaccuracies.
HOW IT WORKS: The two approaches have different setups. For on-device instrumented tests, you write tests in the androidTest source set. You use Room.inMemoryDatabaseBuilder with an instrumentation context to create a temporary database that lives only for the test run. This is Google's recommended approach because it runs your actual queries on the actual Android SQLite engine. For local unit tests, you write tests in the test source set. Since you don't have an Android Context, you must use a library like Robolectric to simulate the Android framework or provide a custom implementation that uses a standard Java SQLite driver (SQLite-JDBC). This is much faster but less reliable.
WHEN TO USE IT: Use instrumented tests as your source of truth for all DAO logic, especially for complex queries, relationships, and migrations. Their accuracy is worth the slower execution time. Use local unit tests for quick feedback during development on simple CRUD (Create, Read, Update, Delete) operations, as they can run in seconds and are ideal for a CI pipeline.
WHEN NOT TO USE IT: Do not write tests for the Room library's own functionality; trust that it works. Focus your tests on your application-specific code: your DAO queries, TypeConverters, and database migrations. A common mistake is writing tests that are not independent. Always clear the database state between tests to ensure one test cannot influence another.
ONE CANONICAL EXAMPLE: To test a UserDao, you would write an instrumented test. First, use a JUnit @Rule to create an in-memory database instance before each test runs. In the test method itself, you would create a User object, call userDao.insert(user), and then immediately fetch it back using a method like userDao.findByLogin("some_id"). Finally, you use an assertion library like Truth to verify that the retrieved user object is not null and contains the correct data. An @After method then closes the database to clean up.
Read the original → developer.android.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.