Tuesday, July 4, 2017

Testing for Exceptions in RxJava 2.x

RxJava 2.x provides useful assertions to test for exception conditions. Assume we have the following class with three methods that result in three different error conditions
  1. No Error
  2. An exception
  3. An exception with a distinct property, in this case an exception message.

We can write one test for each of the three error conditions by using the different asserts available in RxJava
  1. assertNoErrors() 
  2. assertError(Class<? extends Throwable> errorClass)
  3. assertError(Throwable error)
  4. assertError(Predicate<Throwable> errorPredicate)
The ability to write custom errorPredicate is extremely useful when the same exception type is thrown from several locations but each exception instance can have a different property such as the exception message.

Tuesday, June 27, 2017

Tip for writing RxJava code for beginners

Let's say you are using RxJava (or RxAndroid) and your goal is to write code which looks something like the foo method shown in the snippet below. Once you are experienced in writing functional code this appears trivial, however for programmers used to imperative programming style this can appear daunting.

Here is a step by step process which should hopefully make things simpler.

Step 1: Invoke the first method in the desired chain, and use the IDE to assign it's return value to a local variable. This way you can see the type of this expression.
Step 2: Use the local variable created in Step 1 to invoke the second method. If you are unsure about map vs flatMap, simply use map by default. Again, using the IDE assign the result to a local variable. In this new variable a Maybe is nested inside an Observable.

Step 3: This nesting is a hint to change map to a flatMap operation.

Step 4: Follow the above steps for the remaining method calls in the goal.

Step 5: Simply use the IDE to inline all the local variables to reach the goal.

RxJava: Converting to Single type

In RxJava Single is a special type. It must emit exactly one value. Other types like Observable and Maybe can emit no values. If one is not careful these properties can lead to runtime errors in the code.

Converting a Maybe to Single

As shown by the tests in these examples this will rightly result in error.

Converting an Observable to Single

Oddly enough as converting an empty Observable to Single does not result in an error. Maybe that's a bug in RxJava implementation? A quick read of the code does seem to indicate that.

However, the javadoc of Observable#flatMapSingle says "Maps each element of the upstream Observable into SingleSources", and the method returns an Observable. So the behaviour is correct, the second snippet with a non-empty Observable shows that. Maybe the methods could have been named better?

Converting an Observable which emits too many values to a Single rightly results in an error.

Converting a Flowable to Single

Flowable exhibits same behaviour as Observable as shown in these snippets.

Converting a Completable to Single

Just for completeness (no pun intended), this works as expected.