Тестирование транзакций запросов Room в `runBlockingTest` - PullRequest
1 голос
/ 27 января 2020

Как я могу проверить Transaction работу базы данных, insertItineraries для комнаты?

Ошибка

java .lang.IllegalStateException: это задание еще не выполнено

в kotlinx.coroutines.JobSupport.getCompletionExceptionOrNull (JobSupport.kt: 1188) на kotlinx.coroutines.test.TestBuildersKt.runBlockingTest (TestBuilders.kt: 53) на kotlinx.coroutines.test.TestBuildersKt.runBlockingTest $ default (TestBuilders.kt: 45) в com.and.and. db.ItineraryDaoTest.test вставьте маршруты с ногами (ItineraryDaoTest.kt: 44) в sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke (Native * MethodAccessor) 1013: 1302Impor *

МаршрутDao

@Dao
@OpenForTesting
interface ItineraryDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertLegEntities(legs: List<LegEntity>)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertItineraryEntities(itineraries: List<ItineraryEntity>)

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertItineraryLeg(itineraryLegEntities: List<ItineraryLegEntity>)

    @Transaction
    suspend fun insertItineraries(
        itineraries: List<ItineraryEntity>,
        legs: List<LegEntity>,
        itineraryLegEntities: List<ItineraryLegEntity>
    ){
        insertItineraryEntities(itineraries)
        insertLegEntities(legs)
        insertItineraryLeg(itineraryLegEntities)
    }

    @Transaction
    @Query("SELECT * FROM ItineraryEntity")
    fun getItineraryWithLegs(): LiveData<List<ItineraryWithLegs>>
}

МаршрутDaoTest

@ExperimentalCoroutinesApi
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.P])
class ItineraryDaoTest : DbTest() {

    @get:Rule
    var instantTaskExecutorRule = InstantTaskExecutorRule()
    @Captor
    lateinit var captor: ArgumentCaptor<ArrayList<ItineraryWithLegs>>

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
    }

    @Test
    fun `test insert itineraries with legs`() {
        runBlockingTest {
            val observer = mock<Observer<List<ItineraryWithLegs>>>()
            val legs = TestUtil.createLegs(1)
            val itineraries = TestUtil.createItineraries(1)
            val itineraryLegs = TestUtil.createItineraryLegEntities(1)

            skyScannerDatabase.itineraryDao().insertItineraries(itineraries, legs, itineraryLegs)
            skyScannerDatabase.itineraryDao().getItineraryWithLegs().observeForever(observer)

            captor.run {
                verify(observer, times(1)).onChanged(capture())
                assertEquals(itineraryLegs.size, value.size)
            }
        }
    }
}

DbTest

@UseExperimental(ExperimentalCoroutinesApi::class)
abstract class DbTest : CoroutineTestBase() {
    @Rule
    @JvmField
    val countingTaskExecutorRule = CountingTaskExecutorRule()
    lateinit var skyScannerDatabase: SkyScannerDatabase

    @Before
    fun initDb() {
        val app = ApplicationProvider.getApplicationContext<Context>()
        skyScannerDatabase = Room.inMemoryDatabaseBuilder(app, SkyScannerDatabase::class.java)
            .allowMainThreadQueries()
            .setTransactionExecutor(Executors.newSingleThreadExecutor())
            .build()
    }

    @After
    fun closeDb() {
        countingTaskExecutorRule.drainTasks(10, TimeUnit.SECONDS)
        skyScannerDatabase.close()
    }
}

1 Ответ

0 голосов
/ 10 мая 2020

Вы должны протестировать свой DAO, используя @ RunWith (AndroidJUnit4 :: class) аннотацию поверх вашего тестового класса. Запуск в качестве инструментального теста ( тестирует классы в папке androidTest ).

@RunWith(AndroidJUnit4::class)
class YourTestClass {
  @get:Rule
  var instantTaskExecutorRule = InstantTaskExecutorRule()
  lateinit var skyScannerDatabase: SkyScannerDatabase

  @Before
  fun initDb() {
    val app = ApplicationProvider.getApplicationContext<Context>()
    skyScannerDatabase = Room.inMemoryDatabaseBuilder(app, SkyScannerDatabase::class.java)
        .allowMainThreadQueries()
        .setTransactionExecutor(Executors.newSingleThreadExecutor())
        .build()
  }

  @After
  fun closeDb() {
    skyScannerDatabase.close()
  }

  // ...

  @Test
  fun testMethod() = runBlockingTest {
    skyScannerDatabase.itineraryDao().insertItineraries(...)
  }
}

В вашем модуле build.gradle должна быть указана следующая конфигурация.

android {
  // ...

  defaultConfig {
    // ...
    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    // ...
  }
}

// kotlin_coroutines_version = '1.3.3'
// test_arch_core_testing = '2.1.0'
// test_ext_junit_version = '1.1.1'
// test_runner_version = '1.2.0'

dependencies {
  androidTestImplementation "androidx.arch.core:core-testing:$test_arch_core_testing"   
  androidTestImplementation "androidx.test.ext:junit:$test_ext_junit_version"   
  androidTestImplementation "androidx.test:runner:$test_runner_version"  
  androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlin_coroutines_version"
}

Посмотрите на этот пост .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...