Sala de pruebas de unidad y LiveData

Actualmente estoy desarrollando una aplicación con los nuevos componentes de arquitectura de Android . En concreto, estoy implementando una base de datos de sala que devuelve un objeto LiveData en una de sus consultas. La inserción y la consulta funcionan como se esperaba, sin embargo, tengo un problema probando el método de consulta usando la prueba de unidad.

Aquí está el DAO que intento probar:

NotificationDao.kt

 @Dao interface NotificationDao { @Insert fun insertNotifications(vararg notifications: Notification): List<Long> @Query("SELECT * FROM notifications") fun getNotifications(): LiveData<List<Notification>> 

}

Como se puede ver, la función de consulta devuelve un objeto LiveData , si cambio esto para ser sólo una List , un Cursor o básicamente lo que sea, entonces obtengo el resultado esperado, que es el dato insertado en la base de datos.

El problema es que la prueba siguiente siempre fallará porque el value del objeto LiveData siempre es null :

NotificationDaoTest.kt

 lateinit var db: SosafeDatabase lateinit var notificationDao: NotificationDao @Before fun setUp() { val context = InstrumentationRegistry.getTargetContext() db = Room.inMemoryDatabaseBuilder(context, SosafeDatabase::class.java).build() notificationDao = db.notificationDao() } @After @Throws(IOException::class) fun tearDown() { db.close() } @Test fun getNotifications_IfNotificationsInserted_ReturnsAListOfNotifications() { val NUMBER_OF_NOTIFICATIONS = 5 val notifications = Array(NUMBER_OF_NOTIFICATIONS, { i -> createTestNotification(i) }) notificationDao.insertNotifications(*notifications) val liveData = notificationDao.getNotifications() val queriedNotifications = liveData.value if (queriedNotifications != null) { assertEquals(queriedNotifications.size, NUMBER_OF_NOTIFICATIONS) } else { fail() } } private fun createTestNotification(id: Int): Notification { //method omitted for brevity } 

Así que la pregunta es: ¿Alguien sabe de una mejor manera de realizar pruebas de unidad que implican objetos LiveData?

Room calcula el valor de LiveData perezosamente cuando hay un observador.

Puede comprobar la aplicación de ejemplo .

Utiliza un método de utilidad getValue que agrega un observador para obtener el valor:

 public static <T> T getValue(final LiveData<T> liveData) throws InterruptedException { final Object[] data = new Object[1]; final CountDownLatch latch = new CountDownLatch(1); Observer<T> observer = new Observer<T>() { @Override public void onChanged(@Nullable T o) { data[0] = o; latch.countDown(); liveData.removeObserver(this); } }; liveData.observeForever(observer); latch.await(2, TimeUnit.SECONDS); //noinspection unchecked return (T) data[0]; } 

Mejor w / kotlin, usted puede hacer una función de extensiones :).

Cuando devuelve un LiveData de un Dao en el Cuarto hace que la consulta sea asíncrona, y como @yigit dice que Room establece el LiveData#value perezosamente después de iniciar la consulta observando el LiveData . Este patrón es reactivo .

Para las pruebas de unidad que desea que el comportamiento sea síncrono, por lo que debe bloquear el hilo de prueba y esperar a que el valor que se pasa al observador, a continuación, tomar de allí y entonces usted puede afirmar en él.

Esta es una función de extensión de Kotlin para hacer esto:

 fun <T> LiveData<T>.blockingObserve(): T? { var value: T? = null val latch = CountDownLatch(1) val innerObserver = Observer<T> { value = it latch.countDown() } observeForever(innerObserver) latch.await(2, TimeUnit.SECONDS) return value } 

Puedes usarlo así:

 val someValue = someDao.getSomeLiveData().blockingObserve() 
  • Java.lang.UnsatisfiedLinkError: dbopen
  • Ejecutar pruebas de unidad en Guardar con Android Studio
  • Error de cifrado en Android 4.2
  • AssertionFailedError: <class> no tiene constructor público
  • En la unidad de pruebas de Android, cuándo utilizar los casos de prueba?
  • Prueba de la unidad para Android: Cómo burlar el contexto de Android
  • ActivityUnitTestCase getActionBar () devuelve null
  • qué prueba de unidad, en aplicaciones Android
  • Ejecute UiAutomator API desde Android Studio (v0.8)
  • ¿Cómo puedo transferir un dispositivo de prueba de base de datos al dispositivo desde mi aplicación de prueba de unidad
  • Acceso al contexto de la aplicación desde TestSuite en Setup () antes de llamar a getActivity ()
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.