/** * 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 testOnStartRequestsAreAdditiveAndOverflowBecomesMaxValue() { final List<Integer> list = new ArrayList<>(); Observable.just(1, 2, 3, 4, 5) .subscribe( new Observer<Integer>() { @Override public void onStart() { request(2); request(Long.MAX_VALUE - 1); } @Override public void onComplete() {} @Override public void onError(Throwable e) {} @Override public void onNext(Integer t) { list.add(t); } }); assertEquals(Arrays.asList(1, 2, 3, 4, 5), list); }
@Test public void fromArityArgs1() { Observable<String> items = Observable.just("one"); assertEquals((Long) 1L, items.count().toBlocking().single()); assertEquals("one", items.takeLast(1).toBlocking().single()); }
@Ignore("Non-positive requests are relayed to the plugin and is a no-op otherwise") @Test public void testNegativeRequestThrowsIllegalArgumentException() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); final AtomicReference<Throwable> exception = new AtomicReference<>(); Observable.just(1, 2, 3, 4) .subscribe( new Observer<Integer>() { @Override public void onStart() { request(1); } @Override public void onComplete() {} @Override public void onError(Throwable e) { exception.set(e); latch.countDown(); } @Override public void onNext(Integer t) { request(-1); request(1); } }); Assert.assertTrue(latch.await(10, TimeUnit.SECONDS)); Assert.assertTrue(exception.get() instanceof IllegalArgumentException); }
@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 testOnStartCalledOnceViaUnsafeSubscribe() { final AtomicInteger c = new AtomicInteger(); Observable.just(1, 2, 3, 4) .take(2) .unsafeSubscribe( new Observer<Integer>() { @Override public void onStart() { c.incrementAndGet(); request(1); } @Override public void onComplete() {} @Override public void onError(Throwable e) {} @Override public void onNext(Integer t) { request(1); } }); assertEquals(1, c.get()); }
@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 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 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 testTakeFirstOfSome() { Observable<Integer> observable = Observable.just(1, 2, 3); observable.take(1).subscribe(w); verify(w, times(1)).onNext(anyInt()); verify(w).onNext(1); verify(w, times(1)).onComplete(); verify(w, never()).onError(any(Throwable.class)); }
/** This won't compile if super/extends isn't done correctly on generics */ @Test public void testCovarianceOfZip() { Observable<HorrorMovie> horrors = Observable.just(new HorrorMovie()); Observable<CoolRating> ratings = Observable.just(new CoolRating()); Observable.<Movie, CoolRating, Result>zip(horrors, ratings, combine) .toBlocking() .forEach(action); Observable.<Movie, CoolRating, Result>zip(horrors, ratings, combine) .toBlocking() .forEach(action); Observable.<Media, Rating, ExtendedResult>zip(horrors, ratings, combine) .toBlocking() .forEach(extendedAction); Observable.<Media, Rating, Result>zip(horrors, ratings, combine).toBlocking().forEach(action); Observable.<Media, Rating, ExtendedResult>zip(horrors, ratings, combine) .toBlocking() .forEach(action); Observable.<Movie, CoolRating, Result>zip(horrors, ratings, combine); }
@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 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 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 testTakeWhileToList() { final int expectedCount = 3; final AtomicInteger count = new AtomicInteger(); for (int i = 0; i < expectedCount; i++) { Observable.just(Boolean.TRUE, Boolean.FALSE) .takeWhile(v -> v) .toList() .doOnNext(booleans -> count.incrementAndGet()) .subscribe(); } assertEquals(expectedCount, count.get()); }
@Test public void testExtend() { final TestSubscriber<Object> subscriber = new TestSubscriber<>(); final Object value = new Object(); Observable.just(value) .to( onSubscribe -> { onSubscribe.subscribe(subscriber); subscriber.assertNoErrors(); subscriber.assertComplete(); subscriber.assertValue(value); return subscriber.values().get(0); }); }
@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 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 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 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 testCollectToString() { String value = Observable.just(1, 2, 3) .collect( StringBuilder::new, (sb, v) -> { if (sb.length() > 0) { sb.append("-"); } sb.append(v); }) .toBlocking() .last() .toString(); assertEquals("1-2-3", value); }
/** * The error from the user provided Observer is not handled by the subscribe method try/catch. * * <p>It is handled by the AtomicObserver that wraps the provided Observer. * * <p>Result: Passes (if AtomicObserver functionality exists) */ @Test public void testCustomObservableWithErrorInObserverAsynchronous() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); final AtomicInteger count = new AtomicInteger(); final AtomicReference<Throwable> error = new AtomicReference<>(); // FIXME custom built??? Observable.just("1", "2", "three", "4") .subscribeOn(Schedulers.newThread()) .safeSubscribe( new Observer<String>() { @Override public void onComplete() { System.out.println("completed"); latch.countDown(); } @Override public void onError(Throwable e) { error.set(e); System.out.println("error"); e.printStackTrace(); latch.countDown(); } @Override public void onNext(String v) { int num = Integer.parseInt(v); System.out.println(num); // doSomething(num); count.incrementAndGet(); } }); // wait for async sequence to complete latch.await(); assertEquals(2, count.get()); assertNotNull(error.get()); if (!(error.get() instanceof NumberFormatException)) { fail("It should be a NumberFormatException"); } }
@Test public void testStartWithWithScheduler() { TestScheduler scheduler = new TestScheduler(); Observable<Integer> observable = Observable.just(3, 4).startWith(Arrays.asList(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)).onNext(3); inOrder.verify(observer, times(1)).onNext(4); inOrder.verify(observer, times(1)).onComplete(); inOrder.verifyNoMoreInteractions(); }
@Test public void testOfTypeWithPolymorphism() { ArrayList<Integer> l1 = new ArrayList<>(); l1.add(1); LinkedList<Integer> l2 = new LinkedList<>(); l2.add(2); @SuppressWarnings("rawtypes") Observable<List> observable = Observable.<Object>just(l1, l2, "123").ofType(List.class); Subscriber<Object> observer = TestHelper.mockSubscriber(); observable.subscribe(observer); verify(observer, times(1)).onNext(l1); verify(observer, times(1)).onNext(l2); verify(observer, never()).onNext("123"); verify(observer, never()).onError(org.mockito.Matchers.any(Throwable.class)); verify(observer, times(1)).onComplete(); }
@Test public void testCollectToList() { Observable<List<Integer>> o = Observable.just(1, 2, 3).collect(ArrayList::new, (list, v) -> list.add(v)); List<Integer> list = o.toBlocking().last(); assertEquals(3, list.size()); assertEquals(1, list.get(0).intValue()); assertEquals(2, list.get(1).intValue()); assertEquals(3, list.get(2).intValue()); // test multiple subscribe List<Integer> list2 = o.toBlocking().last(); assertEquals(3, list2.size()); assertEquals(1, list2.get(0).intValue()); assertEquals(2, list2.get(1).intValue()); assertEquals(3, list2.get(2).intValue()); }
@Test public void testOnStartCalledOnceViaLift() { final AtomicInteger c = new AtomicInteger(); Observable.just(1, 2, 3, 4) .lift( new Operator<Integer, Integer>() { @Override public Subscriber<? super Integer> apply(final Subscriber<? super Integer> child) { return new Observer<Integer>() { @Override public void onStart() { c.incrementAndGet(); request(1); } @Override public void onComplete() { child.onComplete(); } @Override public void onError(Throwable e) { child.onError(e); } @Override public void onNext(Integer t) { child.onNext(t); request(1); } }; } }) .subscribe(); assertEquals(1, c.get()); }
@Test public void testAmbWith() { TestSubscriber<Integer> ts = new TestSubscriber<>(); Observable.just(1).ambWith(Observable.just(2)).subscribe(ts); ts.assertValue(1); }