스팀 앱 개발기 #34 - WalletViewModel 클래스에 스팀 지갑 정보 읽는 코드 작성
이번 포스트에서는 WalletViewModel 클래스에서 스팀 지갑 정보를 읽는 코드를 작성할 예정입니다.
사전 수정 사항들
본 작업을 시작하기 전에 수정해야 할 사항들이 발견되었습니다. 무엇을 고쳤는지 먼저 간단히 보여드리고 시작하고자 합니다.
- SteemitWallet 데이터 클래스
- 내용이 빈 객체 생성시 파라메터를 사용하지 않는 것이 가능해졌습니다.
- SteemService 인터페이스
- 메소드의 리턴 타입을 Flowable에서 Single로 수정
- SteemRepository 인터페이스, SteemRepositoryImpl 클래스, ReadSteemitWalletUseCase 클래스
- SteemService 인터페이스 수정으로 인하여 메소드 리턴 타입 연쇄적 수정
- SteemRepositoryImpl 클래스
- 서버로부터 읽은 계정 정보인 GetAccountsResponseDTO 객체의 result 필드가 null인지 체크하는 코드 추가
- dorian-steem-ui 모듈의 build.gradle 파일
- dependencies에 모듈, 라이브러리 추가
- dorian-steem-data, dorian-steem-domain 모듈
- RxJava 라이브러리
- "androidx.arch.core:core-testing:2.1.0": 유닛 테스트에 필요
- dependencies에 모듈, 라이브러리 추가
변경된 코드는 아래 소개할 GitHub Commit을 통해 확인 가능합니다.
WalletViewModel 클래스
코드 먼저 보여 드립니다.
class WalletViewModel : ViewModel() {
val steemitWallet = MutableLiveData(SteemitWallet())
val readSteemitWalletUseCase = ReadSteemitWalletUseCase(SteemRepositoryImpl())
// To be deleted...
val text = MutableLiveData<String>("This is wallet Fragment")
fun readSteemitWallet(account: String): Single<Array<SteemitWallet>> {
return readSteemitWalletUseCase(account)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError { error ->
error.printStackTrace()
}
.doOnSuccess { steemitWallets ->
steemitWallet.value = when {
(steemitWallets.size > 0) -> steemitWallets[0]
else -> SteemitWallet()
}
}
}
}
- readSteemitWalletUseCase: 지갑 정보를 읽기 위한 유스 케이스 객체
- steemitWallet: 위 유스 케이스를 통해 가져온 지갑 정보
- 대상 계정이 유효하지 않으면, 빈 값을 갖는 SteemitWallet 객체가 저장됨
- text: 지갑과 무관하여 삭제 예정
- readSteemitWallet: 유스 케이스를 실행하여 지갑 정보 읽음
WalletViewModel 테스트를 위한 WalletViewModelTest 클래스
클래스를 만들었으면, 테스트를 해야겠지요? 아래와 같이 테스트 코드를 작성하였습니다.
// To test WalletViewModel class
class WalletViewModelTest {
@Rule
@JvmField
val instantExecutorRule = InstantTaskExecutorRule()
var walletViewModel = WalletViewModel()
companion object {
@JvmStatic
@BeforeClass
fun setUp() {
// Refer to https://medium.com/@jungil.han/junit-rxjava-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%BB%B4%ED%8C%A8%EB%8B%88%EC%96%B8-%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8-e8d17b674bdd
RxJavaPlugins.setIoSchedulerHandler {
Schedulers.trampoline()
}
RxAndroidPlugins.setInitMainThreadSchedulerHandler {
Schedulers.trampoline()
}
}
@JvmStatic
@AfterClass
fun teardown() {
RxJavaPlugins.reset()
RxAndroidPlugins.reset()
}
}
// Test case 1: Trying to get the wallet of a valid account.
@Test
fun readSteemitWallet_case1() {
walletViewModel.readSteemitWallet("dorian-mobileapp").subscribe { steemitWallets ->
assertEquals("dorian-mobileapp", walletViewModel.steemitWallet.value?.account)
}
}
// Test case 2: Trying to get the wallet of an invalid account.
@Test
fun readSteemitWallet_case2() {
walletViewModel.readSteemitWallet("invalid10293845").subscribe { steemitWallets ->
assertEquals("", walletViewModel.steemitWallet.value?.account)
}
}
}
- instantExecutorRule
- 안드로이드 구성요소 관련 작업들을 한 스레드에서 실행하게 하는 테스트 룰을 적용합니다.
- 특히 라이브데이터를 테스트할 때, 이 룰이 반드시 필요합니다.
- 참고 링크: 안드로이드 테스팅 입문하기(2)
- walletViewModel
- 테스트 대상 객체
- setUp 메소드
- WalletViewModel 객체가 유스 케이스 실행할 때, 어떤 스레드를 사용할지 명시하지만
- 테스트 코드는 안드로이드 기기가 아닌 개발 기기(PC)에서 실행하므로 환경이 안 맞는 문제가 있습니다.
- RxJavaPlugins / RxAndroidPlugins를 사용하여 런타임에 RxJava의 내부 핸들러를 덮어쓸 수 있습니다.
- 자세한 내용은 링크 참고
- teardown 메소드
- setUp 메소드에서 설정한 플러그인들을 해제
- readSteemitWallet_case1 메소드
- 유효한 계정으로 지갑 정보 잘 읽는지 테스트
- readSteemitWallet_case2 메소드
- 유효하지 않은 계정으로 지갑 정보 읽은 결과, SteemitWallet 객체의 account 필드가 빈 값인지 확인
GitHub Commit
마치며...
WalletViewModel 클래스를 테스트 하는 코드를 만드는 과정에서 예상치 못한 시행착오가 있었습니다. 다행히 이를 잘 극복하고 포스트를 쓰게 되었어요.
지난 스팀 앱 개발기
- #33 - 추가 리팩토링: 데이터 모듈의 데이터 클래스의 필드들에 nullable 적용
- #32 - 리팩토링: 데이터 클래스 이름 변경
- #31 - 도메인 모듈에서 정의하는 데이터 클래스들이 DTO 패턴을 따르는 것이 맞는가?
- #30 - 진도를 더 나가기 전에 리팩토링 고려 중
- #29 - 뷰모델, Repository 패턴 그리고 Use Case 패턴의 관계
- #28 - Use Case 패턴 적용
- #27 - Repository 패턴 적용
- #26 - condenser_api.get_accounts API로 받은 계정 자료를 SteemitWalletDTO 타입으로 변환하기
- #25 - SteemClient, SteemService 잘 작동하는지 유닛 테스트
- #24 - API 실행을 담당할 SteemService 인터페이스 정의
- #23 - condenser_api.get_accounts API 연동에 필요한 데이터 클래스 정의
- #22 - API 연동에 필요한 라이브러리 추가
- #21 - 사용자 지갑 정보를 담을 SteemitWallet 클래스 정의
- #20 - 클린 아키텍처를 위한 모듈 구성 (2)
- #19 - 클린 아키텍처를 위한 모듈 구성 (1)
- #18 - VEST로부터 STEEM POWER를 계산하는 방법
- #17 - VEST를 STEEM POWER로 변환하기 위해 필요한 get_dynamic_global_properties API
- #16 - 지갑 내용을 읽기 위해 필요한 API
- #15 - 지갑 서브화면(WalletFragment) 레이아웃 구성해 보기
- #14 - 지갑 서브화면(WalletFragment)에서 계정 인식하기
- #13 - 프로파일 서브화면(ProfileFragment)에서 계정 인식하기
- #12 - 태그 서브화면에서 태그 인식하기
- #11 - 검색 레이아웃을 메인 화면에 적용
- #10 - 태그 및 계정 검색 레이아웃 만들기
- #9 - BaseActivity 클래스 정의 그리고 MainActivity 클래스에 적용
- #8 - BaseFragment 클래스 정의 그리고 기존 프래그먼트들에 적용
- #7 - ProfileFragment 그리고 WalletFragment에 데이터 바인딩 적용
- #6 - 태그별 검색 내용을 보여줄 TagsFragment에 데이터 바인딩 적용
- #5 - GitHub에 소스 올리기
- #4 - 하단 내비게이션의 탭 관련 클래스 이름 수정
- #3 - 하단 내비게이션 바의 아이콘, 텍스트 수정
- #2 - 프로젝트 생성
- #1 - 시작하며...
[광고] STEEM 개발자 커뮤니티에 참여 하시면, 다양한 혜택을 받을 수 있습니다.
Upvoted! Thank you for supporting witness @jswit.