-
테스트(2)BackEnd/RxJava 2023. 7. 16. 10:00반응형
TestSubscriber / TestObserver
- 테스트 용도로 사용되는 소비자 클래스로 TestSubscriber는 Flowable에서, TestObserver는 Observable에서 사용합니다.
- assertXXX 함수를 이용해 통지된 데이터를 검증할 수 있습니다.
- awaitXXX 함수를 이용해 지정된 시간 동안 대기하거나 완료 또는 에러 이벤트가 발생할 때까지 대기할 수 있습니다.
- 완료, 에러, 구독 해지 등의 이벤트 발생 결과 값을 이용해서 데이터를 검증할 수 있습니다.
assertEmpty
- 테스트 시점까지 통지받은 데이터가 없다면 테스트에 성공합니다.
- Observable.empty()로 생성 시 완료를 통지하기 때문에 테스트가 실패합니다.
- 즉, 통지 이벤트 자체가 없는지를 테스트 할 수 있습니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import com.itvillage.common.Car; import com.itvillage.section03.SampleObservable; import io.reactivex.Observable; import io.reactivex.observers.TestObserver; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * assertEmpty를 사용하여 해당 시점까지 통지된 데이터가 있는지 검증하는 예제 */ public class AssertEmptyTest { // 테스트 실패 예제 @Test public void getCarStreamEmptyFailTest(){ // when Observable<Car> observable = SampleObservable.getCarStream(); TestObserver<Car> observer = observable.test(); // then observer.awaitDone(100L, TimeUnit.MILLISECONDS).assertEmpty(); } // 테스트 성공 예제 @Test public void getCarStreamEmptySuccessTest(){ // when Observable<Car> observable = SampleObservable.getCarStream(); TestObserver<Car> observer = observable.delay(1000L, TimeUnit.MILLISECONDS).test(); // then observer.awaitDone(100L, TimeUnit.MILLISECONDS).assertEmpty(); } }
assertValue
- 통지된 데이터가 한 개인 경우에 사용합니다.
- 통지된 데이터가 한 개뿐이므로 파라미터로 입력된 값과 같다면 테스트에 성공합니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import com.itvillage.common.CarMaker; import com.itvillage.section03.SampleObservable; import io.reactivex.Observable; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * assertValue를 이용한 데이터 검증 예제 */ public class AssertValueTest { @Test public void assertValueTest(){ Observable.just("a") .test() .assertValue("a"); } @Test public void getCarMakerAssertValueTest(){ SampleObservable.getCarMakerStream() .filter(carMaker -> carMaker.equals(CarMaker.SAMSUNG)) .test() .awaitDone(1L, TimeUnit.MILLISECONDS) .assertValue(CarMaker.SAMSUNG); } }
assertValues
- 통지된 데이터가 한 개 이상인 경우에 사용합니다.
- 통지된 데이터의 값과 순서가 파라미터로 입력된 데이터의 값과 순서와 일치하면 테스트에 성공합니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import com.itvillage.common.CarMaker; import com.itvillage.section03.SampleObservable; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * assertValues를 이용하여 조건에 맞는 1개 이상의 데이터의 값과 순서과 일치하는지 검증하는 예제 */ public class AssertValuesTest { @Test public void getCarMakerAssertValueTest(){ SampleObservable.getDuplicatedCarMakerStream() .filter(carMaker -> carMaker.equals(CarMaker.CHEVROLET)) .test() .awaitDone(1L, TimeUnit.MILLISECONDS) .assertValues(CarMaker.CHEVROLET, CarMaker.CHEVROLET); } }
assertNoValues
- 해당 시점까지 통지된 데이터가 없으면 테스트에 성공합니다.
- 완료 통지와 에러 통지는 테스트 대상에서 제외됩니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import com.itvillage.utils.LogType; import com.itvillage.utils.Logger; import io.reactivex.Observable; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * assertNoValues를 이용해 통지 시점까지 통지된 데이터가 없는지 검증하는 예제 */ public class AssertNoValuesTest { @Test public void assertNoValuesTest(){ Observable.interval(200L, TimeUnit.MILLISECONDS) .doOnNext(data -> Logger.log(LogType.ON_NEXT, data)) .filter(data -> data > 5) .test() .awaitDone(1000L, TimeUnit.MILLISECONDS) .assertNoValues(); } }
assertResult
- 해당 시점까지 통지를 완료했고, 통지된 데이터와 파라미터로 입력된 데이터의 값과 순서가 같으면 테스트에 성공합니다.
- assertValues와의 차이점은 해당 시점까지 완료 통지를 받았느냐 받지 않았느냐입니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import com.itvillage.utils.LogType; import com.itvillage.utils.Logger; import io.reactivex.Observable; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * assertResult를 사용하여 통지 완료 후, 통지된 데이터와 파라미터로 입력된 데이터의 값과 순서가 일치하는지 검증하는 예제 */ public class AssertResultTest { // 테스트 실패 예제 @Test public void assertResultFailTest(){ Observable.interval(200L, TimeUnit.MILLISECONDS) .doOnNext(data -> Logger.log(LogType.ON_NEXT, data)) .filter(data -> data > 3) .test() .awaitDone(1100L, TimeUnit.MILLISECONDS) .assertResult(4L); } // 테스트 성공 예제 @Test public void assertResultSuccessTest(){ Observable.interval(200L, TimeUnit.MILLISECONDS) .doOnNext(data -> Logger.log(LogType.ON_NEXT, data)) .take(5) .filter(data -> data > 3) .test() .awaitDone(1100L, TimeUnit.MILLISECONDS) .assertResult(4L); } }
assertError
- 해당 시점까지 에러 통지가 있으면 테스트에 성공합니다.
- 단순히 에러 통지가 있었는지의 여부와 구체적으로 발생한 에러가 맞는지를 테스트 할 수 있습니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import io.reactivex.Observable; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * assertError를 이용하여 데이터 통지 중에 에러가 발생했는지를 검증하는 예제 */ public class AssertErrorTest extends RxJavaTest { // 단순히 예외가 발생했는지를 테스트하는 예제 @Test public void assertErrorTest01() { Observable.interval(100L, TimeUnit.MILLISECONDS) .map(data -> { long value; if(data == 4) value = data / 0; else value = data / 2; return value; }) .test() .awaitDone(1000L, TimeUnit.MILLISECONDS) .assertError(Throwable.class); } // 구체적인 예외 클래스를 비교 테스트하는 예제 @Test public void assertErrorTest02() { Observable.interval(100L, TimeUnit.MILLISECONDS) .map(data -> { long value; if(data == 4) value = data / 0; else value = data / 2; return value; }) .test() .awaitDone(1000L, TimeUnit.MILLISECONDS) .assertError(error -> error.getClass() == ArithmeticException.class); } }
assertComplete
- 해당 시점까지 완료 통지가 있으면 테스트에 성공합니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import com.itvillage.section03.SampleObservable; import com.itvillage.utils.TimeUtil; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * assertComplete를 이용하여 A 지점과 B 지점의 매출 합계 처리가 지정된 시간안에 끝나는지 검증하는 예제 */ public class AssertCompleteTest { @Test public void assertCompleteTest() { SampleObservable.getSalesOfBranchA() .zipWith( SampleObservable.getSalesOfBranchB(), (a, b) -> { TimeUtil.sleep(100L); return a + b; } ) .test() .awaitDone(3000L, TimeUnit.MILLISECONDS) .assertComplete(); } }
assertNotComplete
- 해당 시점까지 완료 통지가 없으면 테스트에 성공합니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import com.itvillage.section03.SampleObservable; import com.itvillage.utils.TimeUtil; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * assertNotComplete를 이용하여 A 지점과 B 지점의 매출 합계 처리가 지정된 시간안에 끝나지않는지 검증하는 예제 */ public class AssertNotCompleteTest { @Test public void assertNotCompleteTest() { SampleObservable.getSalesOfBranchA() .zipWith( SampleObservable.getSalesOfBranchB(), (a, b) -> { TimeUtil.sleep(1000L); return a + b; } ) .test() .awaitDone(3000L, TimeUnit.MILLISECONDS) .assertNotComplete(); } }
awaitDone
- 파라미터로 지정된 시간 동안 대기시키거나 지정된 시간 전에 완료 통지나 에러 통지가 있다면 통지가 있을 때까지만 대기시킵니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import com.itvillage.utils.LogType; import com.itvillage.utils.Logger; import io.reactivex.Observable; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * awaitDone 을 이용해서 지정된 시간 또는 완료 통지가 있을때까지 대기하는 예제 */ public class AwaitDoneTest { // 지정된 시간까지 완료 통지가 없이, 해당 시점까지 전달 받은 데이터의 개수가 맞는지 검증하는 예제 @Test public void awaitDoneTest01() { Observable.interval(200L, TimeUnit.MILLISECONDS) .doOnNext(data -> Logger.log(LogType.DO_ON_NEXT, data)) .take(5) .doOnComplete(() -> Logger.log(LogType.DO_ON_COMPLETE)) .doOnError(error -> Logger.log(LogType.DO_ON_ERROR, error.getMessage())) .test() .awaitDone(500L, TimeUnit.MILLISECONDS) .assertNotComplete() .assertValueCount(2); } // 지정된 시간 전에 완료 통지가 있어, 완료 통지 시점까지만 대기하고 전달 받은 데이터의 개수가 맞는지 검증하는 예제 @Test public void awaitDoneTest02() { Observable.interval(200L, TimeUnit.MILLISECONDS) .doOnNext(data -> Logger.log(LogType.DO_ON_NEXT, data)) .take(5) .doOnComplete(() -> Logger.log(LogType.DO_ON_COMPLETE)) .doOnError(error -> Logger.log(LogType.DO_ON_ERROR, error.getMessage())) .test() .awaitDone(1500L, TimeUnit.MILLISECONDS) .assertComplete() .assertValueCount(5); } }
await
- 생산자 쪽에서 완료 통지나 에러 통지가 있을 때까지 쓰레드를 대기시킵니다.
- 파라미터로 지정된 시간 동안 대기하며, 대기 시간 내에 완료 통지가 있었는지 여부를 검증합니다.
package com.itvillage.section04; import com.itvillage.section03.RxJavaTest; import com.itvillage.utils.LogType; import com.itvillage.utils.Logger; import io.reactivex.Observable; import org.junit.Test; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; import java.util.concurrent.TimeUnit; /** * await 을 이용해서 생산자쪽 쓰레드에서 통지가 끝날때까지 또는 지정한 시간만큼 대기하는 예제 */ public class AwaitTest { // 생산자쪽에서 완료 통지를 보낼때까지 대기한 후, 완료 및 통지된 데이터 개수를 검증하는 예제 @Test public void awaitTest() throws InterruptedException { Observable.interval(100L, TimeUnit.MILLISECONDS) .doOnNext(data -> Logger.log(LogType.DO_ON_NEXT, data)) .take(5) .doOnComplete(() -> Logger.log(LogType.DO_ON_COMPLETE)) .doOnError(error -> Logger.log(LogType.DO_ON_ERROR, error.getMessage())) .test() .await() .assertComplete() .assertValueCount(5); } // 지정한 시간동안 대기하면서 대기 시간내에 완료 통지를 받았는지 여부를 검증하는 예제 @Test public void awaitTest02() throws InterruptedException { boolean result = Observable.interval(1000L, TimeUnit.MILLISECONDS) .doOnNext(data -> Logger.log(LogType.DO_ON_NEXT, data)) .take(5) .doOnComplete(() -> Logger.log(LogType.DO_ON_COMPLETE)) .doOnError(error -> Logger.log(LogType.DO_ON_ERROR, error.getMessage())) .test() .await(2000L, TimeUnit.MILLISECONDS); assertThat(result, is(false)); } }
awaitCount
- 파라미터로 지정된 개수 만큼 통지될 때까지 쓰레드를 대기시킵니다.
package com.itvillage.section04; import com.itvillage.utils.LogType; import com.itvillage.utils.Logger; import io.reactivex.Observable; import org.junit.Test; import java.util.concurrent.TimeUnit; /** * awaitCount 를 이용해 지정된 개수만큼 통지가 될 때까지 대기 */ public class AwaitCountTest { // 지정된 개수만큼 대기하고 완료 통지 유무, 통지된 데이터 개수 및 데이터의 값과 순서를 검증하는 예제 @Test public void awaitCountTest() { Observable.interval(200L, TimeUnit.MILLISECONDS) .doOnNext(data -> Logger.log(LogType.DO_ON_NEXT, data)) .take(5) .doOnComplete(() -> Logger.log(LogType.DO_ON_COMPLETE)) .doOnError(error -> Logger.log(LogType.DO_ON_ERROR, error.getMessage())) .test() .awaitCount(3) .assertNotComplete() .assertValueCount(3) .assertValues(0L, 1L, 2L); } }
[참고 자료]
반응형'BackEnd > RxJava' 카테고리의 다른 글
테스트(1) (0) 2023.07.16 디버깅(Debugging) (0) 2023.07.15 스케쥴러(Scheduler) (0) 2023.07.15 Subject (0) 2023.07.14 집계 연산자 (0) 2023.07.13