Room 테스트 하기

ganghee·2022년 2월 25일
0

Test

목록 보기
5/5
post-thumbnail

Room 라이브러리가 설정되어 있다고 가정하고 테스트 기록을 해보겠습니다.
Room 라이브러리에 대한 정보는 여기서 얻어갈 수 있습니다.

테스트 dependency 설정해봅시다.

testImplementation "androidx.room:room-testing:2.4.1"

테스트할 DB 객체 구현입니다.

@Database(entities = [Statement::class], version = 1, exportSchema = false)
@TypeConverters(Converters::class)
internal abstract class CalculatorDatabase : RoomDatabase() {

    abstract fun calculatorDao(): CalculatorDao

    companion object {
        @Volatile
        private var INSTANCE: CalculatorDatabase? = null

        fun getDatabase(context: Context): CalculatorDatabase {
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    CalculatorDatabase::class.java,
                    "calculator_database"
                ).build()
                INSTANCE = instance
                instance
            }
        }
    }
}

Room DB의 DAO 설정입니다.

statement라는 엔티티를 저장하고 리스트를 가져오는 함수가 인터페이스에 설정되었습니다.

@Dao
internal interface CalculatorDao {
    @Query("SELECT * FROM statement")
    fun getAll(): Flow<List<Statement>>

    @Insert
    fun insertStatement(statement: Statement)
}

statement 엔티티 설정입니다.

@Entity(tableName = "statement")
data class Statement(
    @PrimaryKey val uuid: UUID,
    val expression: String,
    val calculateResult: String
) 

이제 본격적으로 테스트 코드를 구현해 봅시다.

@RunWith(AndroidJUnit4::class)
class CalculatorDaoTest {
    private lateinit var appDatabase: CalculatorDatabase

Room DB 테스트는 DB객체를 생성할 때 context를 가져와야 하므로 Instrument 테스트가 진행되어야 합니다. 아래의 android 패키지 안에 설정해주세요.

@Before @After 구현

	@Before
    fun setUp() {
        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
        appDatabase = Room.inMemoryDatabaseBuilder(
            appContext,
            CalculatorDatabase::class.java
        ).build()
    }

    @After
    fun cleanup() {
        appDatabase.close()
    }

InstrumentationRegistry 객체는 androidTest 패키지에서 구현이 가능합니다. Room라이브러리는 inMemoryDatabaseBuilder라는 빌더 함수를 사용합니다. 이 함수는 프로세스가 실행될 때만 객체를 만들어주며 @After의 close()함수를 통해 DB 객체에 접근을 막을 수 있습니다.

테스트 함수 구현

    @Test
    fun insertStatement_checkSavedStatement() = runBlocking {
        val statement = Statement(UUID.randomUUID(), "1 + 1", "2")
        val job = launch(start = CoroutineStart.LAZY) {
                appDatabase.calculatorDao().insertStatement(statement)
            }

        appDatabase.calculatorDao().getAll().take(1).test {
            job.start()
            Assert.assertEquals(statement, awaitItem().first())
        }
    }

Entity를 가져올 때 Flow객체를 이용해서 비동기 구현을 했습니다.

Flow 테스트를 위해 Turbine이라는 라이브러리를 이용하였습니다. runBlocking 코루틴 빌더를 만드면 그 안에 launch를 통해 Job객체를 만들 수 있습니다.

launch 람다 안에 statement를 저장합니다. 그리고 statement 리스트를 가져오는데 take를 통해 하나의 아이템만 가져오도록 설정합니다. 그러면 list중에 하나의 아이템만 반환이됩니다. take를 설정하지 않으면 아래와 같이 오류가 나올 수 있습니다.

app.cash.turbine.AssertionError: Unconsumed events found:

Assert 객체를 통해 검증해주면 테스트 코드가 완성이 됩니다!

0개의 댓글