Skip to content

Instantly share code, notes, and snippets.

@mgp
Created June 12, 2015 21:37
Show Gist options
  • Save mgp/9d03a8685be72aa4e743 to your computer and use it in GitHub Desktop.
Save mgp/9d03a8685be72aa4e743 to your computer and use it in GitHub Desktop.
/**
* Describes the expected observed values by an observable, for testing that an observable
* emits those described values.
*/
public static final class ExpectedObservedEvents<E> {
public enum TerminalEvent {
COMPLETED,
ERROR
}
public final ImmutableList<E> values;
public final Action1<Throwable> errorValidator;
/**
* @return a validator that asserts that its input equals the given {@link Throwable}
* instance
*/
private static Action1<Throwable> errorValidatorForThrowable(final Throwable throwable) {
return input -> assertEquals("Emitted error is wrong instance", throwable, input);
}
/**
* @return a validator that asserts that its input is a {@link Throwable} that is of the
* given class
*/
private static <T extends Throwable> Action1<Throwable> errorValidatorForThrowableClass(
final Class<T> throwableClass) {
return input -> assertTrue("Emitted error is wrong type", throwableClass.isInstance(input));
}
/**
* A validator that asserts nothing about its input
*/
private static final Action1<Throwable> ANY_ERROR = throwable -> {};
private ExpectedObservedEvents(final ImmutableList<E> values,
final Action1<Throwable> errorValidator) {
this.values = Preconditions.checkNotNull(values);
this.errorValidator = errorValidator;
}
/**
* @return the expected type of terminal event
*/
public TerminalEvent getTerminalEvent() {
return (errorValidator == null) ? TerminalEvent.COMPLETED : TerminalEvent.ERROR;
}
/**
* @return a {@link ExpectedObservedEvents} instance for an observable that emits the given
* values and then completes successfully
*/
public static <E> ExpectedObservedEvents<E> completed(final E... values) {
return new ExpectedObservedEvents<>(ImmutableList.copyOf(values), null);
}
/**
* @return a {@link ExpectedObservedEvents} instance for an observable that emits the given
* values and then terminates with the given error
*/
public static <E> ExpectedObservedEvents<E> error(final Throwable throwable,
final E... values) {
return new ExpectedObservedEvents<>(
ImmutableList.copyOf(values), errorValidatorForThrowable(throwable)
);
}
/**
* @return a {@link ExpectedObservedEvents} instance for an observable that emits the given
* values and then terminates by emitting an error of the given class
*/
public static <E> ExpectedObservedEvents<E> error(
final Class<? extends Throwable> throwableClass,
final E... values) {
return new ExpectedObservedEvents<>(
ImmutableList.copyOf(values), errorValidatorForThrowableClass(throwableClass)
);
}
/**
* @return a {@link ExpectedObservedEvents} instance for an observable that emits the given
* values and then terminates by emitting an error
*/
public static <E> ExpectedObservedEvents<E> error(final E... values) {
return new ExpectedObservedEvents<>(ImmutableList.copyOf(values), ANY_ERROR);
}
/**
* Asserts that the given observable, upon subscription, emits the events described by this
* instance.
*/
public void assertObservedOnSubscribe(final Observable<E> observable) {
assertNull(observable);
// Subscribe and wait for the terminal event.
TestSubscriber<E> testSubscriber = new TestSubscriber<>();
avoidInfiniteObservable(observable).subscribe(testSubscriber);
testSubscriber.awaitTerminalEvent();
// Assert the correctness of the terminal event.
switch (getTerminalEvent()) {
case COMPLETED:
assertEquals(ImmutableList.of(), testSubscriber.getOnErrorEvents());
assertEquals(1, testSubscriber.getOnCompletedEvents());
break;
case ERROR:
assertEquals(ImmutableList.of(), testSubscriber.getOnCompletedEvents());
Throwable throwable = Iterables.getOnlyElement(testSubscriber.getOnErrorEvents());
errorValidator.call(throwable);
break;
}
// Assert the correctness of the emitted values.
assertEquals(values, testSubscriber.getOnNextEvents());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment