수색…
비고
모든 Scheduler 메소드가 정적이기 때문에 RxJava 훅을 사용하는 유닛 테스트를 동일한 JVM 인스턴스에서 병렬로 실행할 수 없습니다. 만약 그들이 어디에, 하나의 TestScheduler는 단위 테스트의 중간에 제거됩니다. 기본적으로 Schedulers 클래스 사용의 단점입니다.
TestSubscriber
TestSubscribers를 사용하면 구독자를 만들지 않거나 Action <?>을 구독하여 Observable이 완료되고 예외가 발생하고 훨씬 더 많은 정보가 전달되었는지 확인할 수 있습니다.
시작하기
이 예는 값 1,2,3 및 4가 onNext를 통해 Observable로 전달 된 어설 션을 보여줍니다.
TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
ts.assertValues(1,2,3,4); // Success
assertValues 는 카운트가 assertValues 주장한다. 일부 값만 전달하면 어설 션이 실패합니다.
TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
ts.assertValues(1,2,3); // Fail
assertValues 는 assertValues 수행 할 때 equals 메서드를 사용합니다. 이를 통해 데이터로 처리되는 클래스를 쉽게 테스트 할 수 있습니다.
TestSubscriber<Object> ts = TestSubscriber.create();
Observable.just(new Object(), new Object()).subscribe(ts);
ts.assertValues(new Object(), new Object()); // Fail
이 예제는 equals가 정의되어 있고 Observable의 값을 표명하는 클래스를 보여줍니다.
public class Room {
public String floor;
public String number;
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof Room) {
Room that = (Room) o;
return (this.floor.equals(that.floor))
&& (this.number.equals(that.number));
}
return false;
}
}
TestSubscriber<Room> ts = TestSubscriber.create();
Observable.just(new Room("1", "10")).subscribe(ts);
ts.assertValue(new Room("1", "10"); // Success
또한 단 하나의 항목 만 확인 assertValue 되므로 더 짧은 assertValue 사용합니다.
모든 이벤트 받기
필요한 경우 모든 이벤트를 목록으로 요청할 수도 있습니다.
TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
List<Integer> onNextEvents = ts.getOnNextEvents();
List<Throwable> onErrorEvents = ts.getOnErrorEvents();
List<Notification<Integer>> onCompletedEvents = ts.getOnCompletedEvents();
이벤트에 대한 애셋
이벤트에 대한보다 광범위한 테스트를 수행하려는 경우 getOnNextEvents (또는 getOn*Events )를 선호하는 어설 션 라이브러리와 결합 할 수 있습니다.
Observable<Integer> obs = Observable.just(1,2,3,4)
.filter( x -> x % 2 == 0);
// note that we instanciate TestSubscriber via the constructor here
TestSubscriber<Integer> ts = new TestSubscriber();
obs.subscribe(ts);
// Note that we are not using Observable#forEach here
// but java.lang.Iterable#forEach.
// You should never use Observable#forEach unless you know
// exactly what you're doing
ts.getOnNextEvents()
.forEach( integer -> assertTrue(integer % 2 == 0));
Observable#error
올바른 예외 클래스가 생성되었는지 확인할 수 있습니다.
Observable<Integer> obs = Observable.error(new Exception("I am a Teapot"));
TestSubscriber<Integer> ts = new TestSubscriber<>();
obs.subscribe(ts);
ts.assertError(Exception.class);
정확한 예외가 발생했는지 확인할 수도 있습니다.
Exception e = new Exception("I am a Teapot");
Observable<Integer> obs = Observable.error(e);
TestSubscriber<Integer> ts = new TestSubscriber<>();
obs.subscribe(ts);
ts.assertError(e);
TestScheduler
TestSchedulers를 사용하면 Busy Wait, Threads 또는 다른 것들을 결합하여 시스템 시간을 조작하는 대신 Observables의 시간과 실행을 제어 할 수 있습니다. 예측 가능하고 일관성 있으며 빠른 단위 테스트를 작성하려는 경우 매우 중요합니다. 시간을 조작하고 있기 때문에 스레드가 굶어 죽을 확률이 더 낮아지고 더 느린 머신에서 테스트가 실패하거나 결과를 기다리는 동안 실행 시간이 낭비되지 않습니다.
TestSchedulers는 모든 RxJava 작업에 대해 스케줄러를 사용하는 오버로드를 통해 제공 될 수 있습니다.
TestScheduler testScheduler = new TestScheduler();
TestSubscriber<Integer> subscriber = TestSubscriber.create();
Observable.just(1,2,3)
.delay(10, TimeUnit.SECONDS, testScheduler)
.subscribe(subscriber);
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(11));
} catch (InterruptedException ignored) { }
subscriber.assertValues(1,2,3); // fails
testScheduler.advanceTimeBy(10, TimeUnit.SECONDS);
subscriber.assertValues(1,2,3); // success
TestScheduler는 꽤 기본입니다. 세 가지 방법으로 만 구성됩니다.
testScheduler.advanceTimeBy(amount, timeUnit);
testScheduler.advanceTimeTo(when, timeUnit);
testScheduler.triggerActions();
TestScheduler가 앞으로 어떤 시간에 관련된 모든 동작을 시작해야 할 때 조작 할 수 있습니다.
스케줄러가 작동하는 동안, 이것이 효과적이지 못하기 때문에 TestScheduler가 일반적으로 사용되는 방식이 아닙니다. 스케줄러를 클래스에 전달하면 거의 이익을 얻지 못하는 많은 여분의 코드를 제공하게됩니다. 대신 RxJava의 Schedulers.io () / computation () / etc에 연결할 수 있습니다. 이것은 RxJava의 Hooks로 수행됩니다. 이렇게하면 Scheduler 메소드 중 하나에서 호출에서 반환되는 것을 정의 할 수 있습니다.
public final class TestSchedulers {
public static TestScheduler test() {
final TestScheduler testScheduler = new TestScheduler();
RxJavaHooks.reset();
RxJavaHooks.setOnComputationScheduler((scheduler) -> {
return testScheduler;
});
RxJavaHooks.setOnIOScheduler((scheduler) -> {
return testScheduler;
});
RxJavaHooks.setOnNewThreadScheduler((scheduler) -> {
return testScheduler;
});
return testScheduler;
}
}
이 클래스를 사용하면 스케줄러에 대한 모든 호출에 연결할 테스트 스케줄러를 얻을 수 있습니다. 단위 테스트는 설정에서이 스케줄러를 가져와야합니다. TestScheduler가 당신이 진격 할 때 다른 단위 테스트에서 triggerAction을 시도 할 수도 있기 때문에, 어떤 일반적인 평범한 필드가 아니라 설정에서 그것을 획득하는 것이 좋습니다. 이제 위의 예제가됩니다.
TestScheduler testScheduler = new TestScheduler();
TestSubscriber<Integer> subscriber = TestSubscriber.create();
Observable.just(1,2,3)
.delay(10, TimeUnit.SECONDS, testScheduler)
.subscribe(subscriber);
testScheduler.advanceTimeBy(9, TimeUnit.SECONDS);
subscriber.assertValues(); // success (delay hasn't finished)
testScheduler.advanceTimeBy(10, TimeUnit.SECONDS);
subscriber.assertValues(1,2,3); // success (delay has finished)
그렇게하면 단위 테스트에서 시스템 클럭을 효과적으로 제거 할 수 있습니다 (적어도 RxJava에 관한 한 😆)