화면 종료시 실행 중인 API를 중지하기 위해서는 CompositeDisposable 객체의 clear() 또는 dispose() 함수를 실행하는 것입니다. 이 객체는 BaseViewModel 클래스 안에 정의하였으며, 그것의 onClear() 함수를 오버라이드(override)하여 CompositeDisposable 객체의 clear() 또는 dispose() 함수를 호출시킵니다. 이를 코드로 나타내면 다음과 같습니다.
open class BaseViewModel : ViewModel() {
protected val disposables = CompositeDisposable()
// ...
override fun onCleared() {
disposables.dispose()
super.onCleared()
}
}
어제 작성한 테스트 코드가 실패하는 원인 그리고 해결
- 테스트 대상 클래스, 필드, 메소드: BookSearchViewModel, disposables, onCleared
- 테스트 클래스, 메소드: BookSearchViewModelTest, onCleared
- 원인: disposables 필드는 private 멤버이며, 이에 접근하기 위해 reflection을 사용했으나, BookSearchViewModel 클래스로는 접근 불가
- 해결: BookSearchViewModel 대신 BaseViewModel 클래스를 통해 disposables 멤버에 접근
수정한 테스트 코드
class BookSearchViewModelTest {
// 라이브 데이터 테스트 하려면, 이 객체가 있어야 한다.
// 참고 링크 - https://jeroenmols.com/blog/2019/01/17/livedatajunit5/
@Rule
@JvmField
val instantExecutorRule = InstantTaskExecutorRule()
lateinit var viewModel: BookSearchViewModel
@Before
fun setUp() {
viewModel = BookSearchViewModel()
}
// ...
@Test
fun onCleared() {
viewModel.searchBooks("android")
Thread.sleep(Const.COMMON_DELAY_MILLISECONDS.toLong())
BookSearchViewModel::class.java.declaredMethods.first {
it.name == "onCleared"
}?.let {
it.isAccessible = true
it.invoke(viewModel)
}
BaseViewModel::class.java.declaredFields.first {
it.name == "disposables"
}?.let {
it.isAccessible = true
val disposables = it.get(viewModel) as CompositeDisposable
Assert.assertEquals(0, disposables.size())
}
}
}
마치며...
이번 단위 테스트를 통해 reflection을 사용해보았으나, 아직 낯설다는 느낌입니다. 이에 대해 좀 더 공부를 해볼 필요성을 느꼈습니다. 내일은 이에 대한 내용을 정리하고 샘플 코드를 만들어 보겠습니다.
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit