ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 테스트(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

    댓글

Designed by Tistory.