2023. 4. 23. 02:47ㆍandroid
JUnit4를 이용한 Room DabaBase Test
지난번 Viewmodel, Repository의 unit test에 이어서 오늘은 room database의 instrumentation Test를 진행하는 방법을 작성해 보겠습니다. room database를 test 하기 위해 겪은 과정, 이슈들을 다뤄보겠습니다.
Dependency는 아래 포스트의 Dependency를 복붙 하시면 됩니다!
2023.04.21 - [android] - JUnit4를 사용한 Viewmodel , usecase , repository 패턴 Unit Test
Room Database Instrumentation Test
room db의 테스트를 진행하기 위해 먼저 파일을 만들어줍니다.
위치는
다른 위치에 만들게 되면 오류가 발생하므로 꼭 androidTest 폴더에서 만들어야 합니다.
그리고 파일이름은 아무거나 상관없으니 만들어주시면 준비 끝!
그리고 필요한 게 2가지 있습니다.
1. Database
2. Dao
Database
먼저 room을 사용하기 때문에 당연히 db 연결을 위한 Database 클래스를 만들어줘야 합니다.
여기서 dao 도 지정해 줍니다.
@Database(
entities = [Note::class],
version = 1,
exportSchema = false
)
abstract class NoteDataBase : RoomDatabase() {
companion object{
const val DB_NAME = "noteDB"
}
abstract fun dao() : Dao
}
Dao
Dao 인터페이스를 만들어줍니다.
@Dao
interface Dao {
@Query("SELECT * FROM note")
fun getNotes(): Flow<List<Note>>
@Query("SELECT * FROM note WHERE id= :id")
suspend fun getNote(id: Int) : Note
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertNote(note: Note)
@Delete
suspend fun deleteNote(note: Note)
}
Test 클래스
테스트 함수를 보겠습니다.
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
class NoteDatabaseDAOTest {
private lateinit var noteDatabase: NoteDataBase
private lateinit var noteDao: Dao
@Before
fun setUp(){
val context = ApplicationProvider.getApplicationContext<Context>()
noteDatabase = Room.inMemoryDatabaseBuilder(context, NoteDataBase::class.java).build()
noteDao = noteDatabase.dao()
}
@After
fun closeDB(){
noteDatabase.close()
}
@Test
fun insertTest() = runTest {
//given
val note = Note(0,"0","0",0L,0)
//when
noteDao.insertNote(note)
//then
val result = noteDao.getNotes().first()
Assert.assertEquals(1, result.size)
}
}
어노테이션은 코루틴 테스트를 위한 것이고 runner를 지정해 줍니다.
SetUp을 보시면 db를 만들 때 context가 필요합니다. Context 객체는 데이터베이스 생성 시 리소스에 대한 액세스를 제공하고, 데이터베이스를 생성하는 데 필요한 애플리케이션의 상태 정보를 가져오는 데 사용됩니다. 그런 이유로 context를 생성하고 noteDatabase를 inMemoryDatabaseBuilder를 통해 만들어줍니다. inMemoryDatabaseBuilder의 역할을 디스크에 저장하지 않고 메모리 상에서만 동작하는 DB를 만들 수 있게 합니다. 뒤에 .allowMainThreadQueries()를 사용하기도 하는데 이 메서드의 역할은 메인스레드에서 DB에 접근할 수 있게 합니다. 왜 메인스레드에서 접근하게 하냐? 원래 메인스레드에서는 UI를 업데이트합니다. UI 업데이트 말고 데이터베이스나 네트워크 같은 무거운 작업을 메인스레드에서 처리하게 되면 스레드가 무거워져서 작동성이 떨어지거나 에러가 발생할 수 있습니다. 그래서 별도의 스레드에서 무거운 작업들인 DB나 네트워크 같은 작업을 처리합니다. 하지만 테스트를 위해 간단한 동작을 그냥 메인스레드를 통해 처리한다고 허용하여 작업을 간편하게 하기 위해 사용합니다.
@Before
fun setUp(){
val context = ApplicationProvider.getApplicationContext<Context>()
noteDatabase = Room.inMemoryDatabaseBuilder(context, NoteDataBase::class.java).build()
noteDao = noteDatabase.dao()
}
insert 테스트
note 객체를 하나 생성해서 insert함수를 실행합니다. 그리고 결과를 확인합니다. 간단하게 결과를 확인하려고 size만 체크하였는데 결과를 다른 방식으로 체크하시길 추천드립니다.
@Test
fun insertTest() = runTest {
//given
val note = Note(0,"0","0",0L,0)
//when
noteDao.insertNote(note)
//then
val result = noteDao.getNotes().first()
Assert.assertEquals(1, result.size)
}
구현하는 과정에 어려운 부분은 크게 있지 않습니다. 발생할 수 있는 에러라면 빌드 이슈이거나 오타 정도가 있을 것 같습니다. 사실 저는 unit test 폴더에 넣어두고 왜 계속 실행이 안되지 하면서 머리를 싸맸는데 이런 실수 안 하시길 바랍니다...
이상으로 room database 하는 방법을 알아보았습니다. 읽어주셔서 감사합니다!
'android' 카테고리의 다른 글
android contentProvider를 이용하여 공유 저장소 미디어 파일에 엑세스 하는 방법을 통한 예시와 공홈 번역 및 공부 (0) | 2023.05.27 |
---|---|
Retrofit2 MockServer test case 작성 (0) | 2023.04.27 |
JUnit4를 사용한 Viewmodel , usecase , repository 패턴 Unit Test (0) | 2023.04.21 |
한 번의 글로는 이해가 안 가는 안드로이드 테스트 ( 유닛 테스트 & 계측 테스트 ) (0) | 2023.04.21 |
Android Compose (0) | 2022.09.28 |