Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force an immediate evaluation on stream in Java8

I am wondering how can I force an immediate evaluate on each map function in Java8 ? The situation I have now is that I need to do multiple levels transforming (from ObjectA -> ObjectB -> ObjectC -> ObjectD), and there could be a failure (throw exception) on every level of this transforming for some object. For example

 // stream -> map -> collect sequence
 lists.stream()
      .map(aToB)
      .collect(Collectors.toList())
      .stream()
      .map(bToC)
      .collect(Collectors.toList())
      .stream()
      .map(cToD)
      .collect(Collectors.toList())

 // Try api is from javaslangs
 Function<ObjectA, ObjectB> aToB = a -> Try.of(() -> .....)
                                           .onFailure(....)
                                           .get();

 Function<ObjectB, ObjectC> bToC = b -> Try.of(() -> .....)
                                           .onFailure(....)
                                           .get();

 Function<ObjectC, ObjectD> cToD = c -> Try.of(() -> .....)
                                           .onFailure(....)
                                           .get();

I wanna to test each transition in my unit test such as test if the test thrown an exception, and if A unsuccessfully transformed to C when there's an exception when transforming A to B something like that, but with lazy evaluation, this becomes impossible to test, and the only way I can think of is to do this sequence of steam() -> map(...) -> collect(...) calls to force an immediate evaluation. I am wondering is there a better way to write this.

like image 428
peter Avatar asked Feb 01 '16 22:02

peter


2 Answers

Some simple thoughts here:

  • Test the whole chain of streaming operations on single-element collections. Verify that exceptions are thrown where you expect.
  • Don't worry about testing the stream framework; just apply the functions directly, yourself, in tests, rather than going through the streams.

Generally speaking, don't try to deal with the lazy evaluation in your tests: test the functions, and trust the stream framework to do the right thing in real code.

like image 105
Louis Wasserman Avatar answered Sep 28 '22 07:09

Louis Wasserman


You can write a static helper method that collects into a collection and then returns that collection's stream and wrap individual steps of the stream pipeline into that helper.

You should be aware that this alters the semantics of the stream.

For example an infinite stream source might fail if handled in this matter even though the complete stream pipeline might succeed if it is terminated with a short-circuiting operation. Similarly parallelism and concurrency properties might get altered. So you would end up testing something different from the stream pipeline itself.

Instead it's probably a better idea to just test the full stream pipeline to deliver the expected outputs for possible input scenarios and possibly test the mapping Function separately on various kinds of inputs.

like image 39
the8472 Avatar answered Sep 28 '22 07:09

the8472