@Test public void fromArray() { String[] items = new String[] {"one", "two", "three"}; assertEquals((Long) 3L, Observable.fromArray(items).count().toBlocking().single()); assertEquals("two", Observable.fromArray(items).skip(1).take(1).toBlocking().single()); assertEquals("three", Observable.fromArray(items).takeLast(1).toBlocking().single()); }
@Test public void fromArityArgs1() { Observable<String> items = Observable.just("one"); assertEquals((Long) 1L, items.count().toBlocking().single()); assertEquals("one", items.takeLast(1).toBlocking().single()); }
/** * A reduce on an empty Observable and a seed should just pass the seed through. * * <p>This is confirmed at https://github.com/ReactiveX/RxJava/issues/423#issuecomment-27642456 */ @Test public void testReduceWithEmptyObservableAndSeed() { Observable<Integer> observable = Observable.range(1, 0); int value = observable.reduce(1, (t1, t2) -> t1 + t2).toBlocking().last(); assertEquals(1, value); }
/** * The error from the user provided Observable is handled by the subscribe try/catch because this * is synchronous * * <p>Result: Passes */ @Test public void testCustomObservableWithErrorInObservableSynchronous() { final AtomicInteger count = new AtomicInteger(); final AtomicReference<Throwable> error = new AtomicReference<>(); // FIXME custom built??? Observable.just("1", "2") .concatWith(Observable.error(() -> new NumberFormatException())) .subscribe( new Observer<String>() { @Override public void onComplete() { System.out.println("completed"); } @Override public void onError(Throwable e) { error.set(e); System.out.println("error"); e.printStackTrace(); } @Override public void onNext(String v) { System.out.println(v); count.incrementAndGet(); } }); assertEquals(2, count.get()); assertNotNull(error.get()); if (!(error.get() instanceof NumberFormatException)) { fail("It should be a NumberFormatException"); } }
@Test public void testReduceWithInitialValue() { Observable<Integer> observable = Observable.just(1, 2, 3, 4); observable.reduce(50, (t1, t2) -> t1 + t2).subscribe(w); // we should be called only once verify(w, times(1)).onNext(anyInt()); verify(w).onNext(60); }
@Test public void testFirstWithPredicateOfNoneMatchingThePredicate() { Observable<Integer> observable = Observable.just(1, 3, 5, 7, 9, 7, 5, 3, 1); observable.filter(IS_EVEN).first().subscribe(w); verify(w, never()).onNext(anyInt()); verify(w, never()).onComplete(); verify(w, times(1)).onError(isA(NoSuchElementException.class)); }
@Test public void testFirstOfNone() { Observable<Integer> observable = Observable.empty(); observable.first().subscribe(w); verify(w, never()).onNext(anyInt()); verify(w, never()).onComplete(); verify(w, times(1)).onError(isA(NoSuchElementException.class)); }
@Test public void testTakeFirstOfNone() { Observable<Integer> observable = Observable.empty(); observable.take(1).subscribe(w); verify(w, never()).onNext(anyInt()); verify(w, times(1)).onComplete(); verify(w, never()).onError(any(Throwable.class)); }
@Test public void testTakeFirstWithPredicateOfNoneMatchingThePredicate() { Observable<Integer> observable = Observable.just(1, 3, 5, 7, 9, 7, 5, 3, 1); observable.takeFirst(IS_EVEN).subscribe(w); verify(w, never()).onNext(anyInt()); verify(w, times(1)).onComplete(); verify(w, never()).onError(any(Throwable.class)); }
public void testTakeFirstWithPredicateOfSome() { Observable<Integer> observable = Observable.just(1, 3, 5, 4, 6, 3); observable.takeFirst(IS_EVEN).subscribe(w); verify(w, times(1)).onNext(anyInt()); verify(w).onNext(4); verify(w, times(1)).onComplete(); verify(w, never()).onError(any(Throwable.class)); }
@Test public void testCountError() { Observable<String> o = Observable.error(() -> new RuntimeException()); o.count().subscribe(w); verify(w, never()).onNext(anyInt()); verify(w, never()).onComplete(); verify(w, times(1)).onError(any(RuntimeException.class)); }
@Test public void testCountZeroItems() { Observable<String> observable = Observable.empty(); observable.count().subscribe(w); // we should be called only once verify(w, times(1)).onNext(anyLong()); verify(w).onNext(0L); verify(w, never()).onError(any(Throwable.class)); verify(w, times(1)).onComplete(); }
@Test public void fromIterable() { ArrayList<String> items = new ArrayList<>(); items.add("one"); items.add("two"); items.add("three"); assertEquals((Long) 3L, Observable.fromIterable(items).count().toBlocking().single()); assertEquals("two", Observable.fromIterable(items).skip(1).take(1).toBlocking().single()); assertEquals("three", Observable.fromIterable(items).takeLast(1).toBlocking().single()); }
@Test public void testIgnoreElements() { Observable<Integer> observable = Observable.just(1, 2, 3).ignoreElements(); Subscriber<Object> observer = TestHelper.mockSubscriber(); observable.subscribe(observer); verify(observer, never()).onNext(any(Integer.class)); verify(observer, never()).onError(any(Throwable.class)); verify(observer, times(1)).onComplete(); }
@Test public void testCountAFewItems() { Observable<String> observable = Observable.just("a", "b", "c", "d"); observable.count().subscribe(w); // we should be called only once verify(w, times(1)).onNext(anyLong()); verify(w).onNext(4L); verify(w, never()).onError(any(Throwable.class)); verify(w, times(1)).onComplete(); }
@Test public void testMaterializeDematerializeChaining() { Observable<Integer> obs = Observable.just(1); Observable<Integer> chained = obs.materialize().dematerialize(); Subscriber<Integer> observer = TestHelper.mockSubscriber(); chained.subscribe(observer); verify(observer, times(1)).onNext(1); verify(observer, times(1)).onComplete(); verify(observer, times(0)).onError(any(Throwable.class)); }
@Test public void testContainsWithEmptyObservable() { Observable<Boolean> observable = Observable.<String>empty().contains("a"); Subscriber<Object> observer = TestHelper.mockSubscriber(); observable.subscribe(observer); verify(observer, times(1)).onNext(false); verify(observer, never()).onNext(true); verify(observer, never()).onError(org.mockito.Matchers.any(Throwable.class)); verify(observer, times(1)).onComplete(); }
/** A reduce should fail with an NoSuchElementException if done on an empty Observable. */ @Test(expected = NoSuchElementException.class) public void testReduceWithEmptyObservable() { Observable<Integer> observable = Observable.range(1, 0); observable .reduce((t1, t2) -> t1 + t2) .toBlocking() .forEach( t1 -> { // do nothing ... we expect an exception instead }); fail("Expected an exception to be thrown"); }
@Test public void testContains() { Observable<Boolean> observable = Observable.just("a", "b", "c").contains("b"); // FIXME nulls not allowed, changed to "c" Subscriber<Boolean> observer = TestHelper.mockSubscriber(); observable.subscribe(observer); verify(observer, times(1)).onNext(true); verify(observer, never()).onNext(false); verify(observer, never()).onError(org.mockito.Matchers.any(Throwable.class)); verify(observer, times(1)).onComplete(); }
@Test public void testContainsWithInexistence() { Observable<Boolean> observable = Observable.just("a", "b").contains("c"); // FIXME null values are not allowed, removed Subscriber<Object> observer = TestHelper.mockSubscriber(); observable.subscribe(observer); verify(observer, times(1)).onNext(false); verify(observer, never()).onNext(true); verify(observer, never()).onError(org.mockito.Matchers.any(Throwable.class)); verify(observer, times(1)).onComplete(); }
@Test @Ignore("null values are not allowed") public void testContainsWithNull() { Observable<Boolean> observable = Observable.just("a", "b", null).contains(null); Subscriber<Object> observer = TestHelper.mockSubscriber(); observable.subscribe(observer); verify(observer, times(1)).onNext(true); verify(observer, never()).onNext(false); verify(observer, never()).onError(org.mockito.Matchers.any(Throwable.class)); verify(observer, times(1)).onComplete(); }
@Test public void testCreate() { Observable<String> observable = Observable.just("one", "two", "three"); Subscriber<String> observer = TestHelper.mockSubscriber(); observable.subscribe(observer); verify(observer, times(1)).onNext("one"); verify(observer, times(1)).onNext("two"); verify(observer, times(1)).onNext("three"); verify(observer, never()).onError(any(Throwable.class)); verify(observer, times(1)).onComplete(); }
@Test public void testOfType() { Observable<String> observable = Observable.just(1, "abc", false, 2L).ofType(String.class); Subscriber<Object> observer = TestHelper.mockSubscriber(); observable.subscribe(observer); verify(observer, never()).onNext(1); verify(observer, times(1)).onNext("abc"); verify(observer, never()).onNext(false); verify(observer, never()).onNext(2L); verify(observer, never()).onError(org.mockito.Matchers.any(Throwable.class)); verify(observer, times(1)).onComplete(); }
@Test public void testPublishLast() throws InterruptedException { final AtomicInteger count = new AtomicInteger(); ConnectableObservable<String> connectable = Observable.<String>create( observer -> { observer.onSubscribe(EmptySubscription.INSTANCE); count.incrementAndGet(); new Thread( () -> { observer.onNext("first"); observer.onNext("last"); observer.onComplete(); }) .start(); }) .takeLast(1) .publish(); // subscribe once final CountDownLatch latch = new CountDownLatch(1); connectable.subscribe( value -> { assertEquals("last", value); latch.countDown(); }); // subscribe twice connectable.subscribe(); Disposable subscription = connectable.connect(); assertTrue(latch.await(1000, TimeUnit.MILLISECONDS)); assertEquals(1, count.get()); subscription.dispose(); }
/** * https://github.com/ReactiveX/RxJava/issues/198 * * <p>Rx Design Guidelines 5.2 * * <p>"when calling the Subscribe method that only has an onNext argument, the OnError behavior * will be to rethrow the exception on the thread that the message comes out from the Observable. * The OnCompleted behavior in this case is to do nothing." * * @throws InterruptedException */ @Test @Ignore("Subscribers can't throw") public void testErrorThrownWithoutErrorHandlerAsynchronous() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); final AtomicReference<Throwable> exception = new AtomicReference<>(); Observable.create( observer -> { new Thread( () -> { try { observer.onError(new Error("failure")); } catch (Throwable e) { // without an onError handler it has to just throw on whatever thread // invokes it exception.set(e); } latch.countDown(); }) .start(); }) .subscribe(); // wait for exception latch.await(3000, TimeUnit.MILLISECONDS); assertNotNull(exception.get()); assertEquals("failure", exception.get().getMessage()); }
@Test public void testTakeWithErrorInObserver() { final AtomicInteger count = new AtomicInteger(); final AtomicReference<Throwable> error = new AtomicReference<>(); Observable.just("1", "2", "three", "4") .take(3) .safeSubscribe( new Observer<String>() { @Override public void onComplete() { System.out.println("completed"); } @Override public void onError(Throwable e) { error.set(e); System.out.println("error"); e.printStackTrace(); } @Override public void onNext(String v) { int num = Integer.parseInt(v); System.out.println(num); // doSomething(num); count.incrementAndGet(); } }); assertEquals(2, count.get()); assertNotNull(error.get()); if (!(error.get() instanceof NumberFormatException)) { fail("It should be a NumberFormatException"); } }
@Test public void testEmptyIsEmpty() { Observable.<Integer>empty().subscribe(w); verify(w).onComplete(); verify(w, never()).onNext(any(Integer.class)); verify(w, never()).onError(any(Throwable.class)); }
@Test public void testCompose() { TestSubscriber<String> ts = new TestSubscriber<>(); Observable.just(1, 2, 3).compose(t1 -> t1.map(String::valueOf)).subscribe(ts); ts.assertTerminated(); ts.assertNoErrors(); ts.assertValues("1", "2", "3"); }
@Test public void testJustWithScheduler() { TestScheduler scheduler = new TestScheduler(); Observable<Integer> observable = Observable.fromArray(1, 2).subscribeOn(scheduler); Subscriber<Integer> observer = TestHelper.mockSubscriber(); observable.subscribe(observer); scheduler.advanceTimeBy(1, TimeUnit.MILLISECONDS); InOrder inOrder = inOrder(observer); inOrder.verify(observer, times(1)).onNext(1); inOrder.verify(observer, times(1)).onNext(2); inOrder.verify(observer, times(1)).onComplete(); inOrder.verifyNoMoreInteractions(); }
@Ignore // FIXME throwing is not allowed from the create?! @Test public void testOnSubscribeFails() { Subscriber<String> observer = TestHelper.mockSubscriber(); final RuntimeException re = new RuntimeException("bad impl"); Observable<String> o = Observable.create( s -> { throw re; }); o.subscribe(observer); verify(observer, times(0)).onNext(anyString()); verify(observer, times(0)).onComplete(); verify(observer, times(1)).onError(re); }