brunch

You can make anything
by writing

C.S.Lewis

by 이승현 Aug 14. 2017

MVP & Rx unit test

Junit & Mockito & Rx

MVP & Rx unit test


MVP unit test와 Rx에 대한 내용은 이전에 작성했던 글들을 통해 확인하실 수 있습니다.

이번에는 Rx를 결합한 MVP unit test에 대해서 작성하겠습니다.





MVP Presenter logic


#01 MVP pattern logic


특정 동작에 대해 Presenter가 view와 model 간 상호작용을 잘 수행하는지를 테스트하려 합니다.


아래 코드는 Model(Repository)에서 RxJava의 Single 형태로 데이터를 파싱 하여 가져와 이를 기반으로 view를 업데이트하는 Presenter입니다.

이 코드를 기반으로 Unit test 작성법에 대해 알아보겠습니다.

#02 Presenter codes






Create a Local Unit Test


#01 build.gradle


build.gradle에 아래와 같이 dependencies를 추가합니다.

#03 app build.gradle





#02 New Test java class


"module-name/src/test/java/." 디렉터리에 Test java class를 생성합니다.

Model-Presenter-View에서 UI test가 아닌 Presenter의 Unit test만 하기 위해서 "PresenterTest.java"을 생성합니다.


#04 MainGridPresenterTest





#03 @Before


가장 먼저 해야 할 일은 @Before annotation 메서드를 작성하는 것입니다.

보통 테스트를 하기 전에 필요한 객체를 초기화하거나 기타 설정들을 위해 이용합니다.

@Before 메서드는 모든 테스트 전에 실행되기 때문에 만약 4개의 테스트가 있는 경우 4번 실행됩니다.

즉, 이전 @Before 메서드의 영향을 받지 않습니다.


#05 4 times @Before


PresenterTest에서는 Model, View, Presenter 인스턴스 변수를 생성하기 위해 @Before를 이용합니다.

@Before
public void setup() {
    ...
}


이때 실제 Model과 View 인스턴스 변수를 생성하기에 공수도 많이 들어가지만 안드로이드 프레임워크의 영향을 받기 때문에 Mockito.mock() API를 이용해 mock Model과 mock View를 생성합니다.

#06-1 MainGridPresenterTest - setup()


그리고 이를 기반으로 Presenter 인스턴스 변수도 생성합니다.

@Before 메서드에서 정의한 모의 객체들을 이용해 테스트 및 상호 작용에 적합한 동작을 정의할 수 있습니다.

#06-2 MainGridPresenterTest - setup()





#04 @BeforeClass


테스트를 하기 전에 @BeforeClass annotation 메서드를 작성해야 합니다.

@BeforeClass는 @Before와 달리 모든 테스트 전에 단 한 번만 실행됩니다.


#07 1 time @BeforeClass


기본적으로 Junit에서는 아래와 같이 안드로이드의 메인 스레드를 이용할 수 없습니다.

조금 더 자세히 말하면 AndroidSchedulers.mainThread()가 반환하는 기본 Scheduler가 Android에 의존하여, JVM에서 인스턴스화 할 수 없기 때문입니다.

따라서 이를 이용하기 위해 @BeforeClass를 이용한 사전 작업이 필요합니다.

#08 Presenter - threads


RxAndroid의 RxAndroidPlugins는 RxAndroid의 Scheduler를 Overriding 하기 위한 API들을 제공하고 있습니다. 테스트를 실행하기 전에 이를 이용하여 RxAndroid의 Scheduler를 다른 Scheduler로 변환하여 이 문제를 피할 수 있습니다.

#09 MainGridPresenterTest - setUpRxSchedulers()





#05 @Test


@Test annotation을 이용하여 테스트할 메서드를 작성합니다.

@Test가 선언되면 이 메서드는 테스트 대상임을 의미합니다.


우선 Presenter에서 view 메서드를 호출하는 로직을 살펴봐야 합니다.

1. Presenter - startParsing() 호출
2. Repository - parsing() 호출
3. Repository에서 Single<List<ContentInfoModel> 반환
4. Single<List<ContentInfoModel> - onSuccess(list)나 onError(e)를 통해 view 메서드 호출 
#10 MainGridPresenter


이를 기반으로 "showList", "showEmpty", "showError" @Test 메서드를 생성합니다.

여기서 주의할 점은 Single을 toFlowable() API를 통해 Flowable 형태로 변환해줘야 합니다.

Single, Completable, Maybe는 기본적으로 TestSubscriber을 이용할 수 없기에 Flowable나 Observable 형태로 변환해야 합니다.


#11 MainGridPresenterTest - showList()


#12 MainGridPresenterTest - showEmpty()


#13 MainGridPresenterTest - showError()





Run Test


테스트를 실행하려면 다음 단계를 진행해야 합니다.


1. 안드로이드 스튜디오의 "Run > Edit Configurations"를 선택합니다.

#14 Edit Run/Debug Configurations


2. "Run/Debug Configurations" 대화 상자에서 "Android JUnit"을 추가합니다.

#15 Add Android JUnit


3. 이름, 테스트 종류, 모듈 등 여러 옵션을 선택하고 "Apply" 버튼을 선택합니다.

#16 Apply Test options


4. "Run" 버튼을 선택 해 테스트를 실행합니다. 

#17 Run Test




Test result


테스트 결과 다음과 같이 볼 수 있습니다.

모든 테스트 성공 시 프로그래스 바가 녹색으로 표시되고, 실패 시 빨간색으로 표시됩니다.


#18 Test Result - Passed
#19 Test Result - Failed







Rx를 이용한 MVP 패턴의 Presenter 테스트 코드도 알고 보면 어렵지 않습니다.

물론 좀 더 복잡한 로직이거나 Rx의 Operation들이 많으면 공수도 많이 들어가겠지만, Presenter의 호출 로직만을 판단하기 위한 테스트에서는 흔치 않을 거라 생각합니다.

이에 대해 좀 더 자세히 알고 싶으면 RxJava의 Test 코드들을 참고하시면 될 거 같습니다.


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari