<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" 
  xmlns:content="http://purl.org/rss/1.0/modules/content/" 
  xmlns:dc="http://purl.org/dc/elements/1.1/" 
  xmlns:atom="http://www.w3.org/2005/Atom" 
  xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" 
  xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>Deep Dive on Solid Soft</title>
    <link>https://blog.solidsoft.pl/categories/deep-dive/</link>
    <description>Recent content in Deep Dive on Solid Soft</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>©{year}, All Rights Reserved</copyright>
    <lastBuildDate>Wed, 15 Apr 2020 10:00:00 +0200</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>2</sy:updateFrequency>
    
        <atom:link href="https://blog.solidsoft.pl/categories/deep-dive/index.xml" rel="self" type="application/rss+xml" />
    
    
    

      
      <item>
        <title>Spock vs JUnit 5 - the ultimate feature comparison</title>
        <link>https://blog.solidsoft.pl/2020/04/15/spock-vs-junit-5-the-ultimate-feature-comparison/</link>
        <pubDate>Wed, 15 Apr 2020 10:00:00 +0200</pubDate>
        
        <atom:modified>Wed, 15 Apr 2020 10:00:00 +0200</atom:modified>
        <guid>https://blog.solidsoft.pl/2020/04/15/spock-vs-junit-5-the-ultimate-feature-comparison/</guid>
        <description>What is the best testing framework for Java code nowadays? Spock or JUnit 5? Check it out in this ultimate feature comparison.
  Spock was a game changer for all the people struggling with unit testing in JUnit 4. Compact syntax, parameterized tests or flexibility to mention just a few advantages. Over 10 years after JUnit 4.0, the brand new, written from scratch, Java 8 optimized Junit 5 has been released.</description>
        <content:encoded>&lt;blockquote&gt;
&lt;p&gt;What is the best testing framework for Java code nowadays? Spock or JUnit 5? Check it out in this ultimate feature comparison.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;figure &gt;
  
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2020/spock-vs-junit5.png&#34;  style=&#34;width:;height:;&#34;/&gt;
  
  
&lt;/figure&gt;

&lt;p&gt;Spock was a game changer for all the people struggling with unit testing in JUnit 4. Compact syntax, parameterized tests or flexibility to mention just a few advantages. Over 10 years after JUnit 4.0, the brand new, written from scratch, Java 8 optimized Junit 5 has been released. And time has not stopped then.&lt;/p&gt;
&lt;p&gt;In this blog post, I will compare selected areas of Spock and JUnit 5 to give you an overview how the situation looks like nowadays. I will try to answer the question if its time for Spock to fade into oblivion or maybe quite the opposite it is still light years ahead of JUnit 5.&lt;/p&gt;
&lt;div class=&#34;notices info&#34; &gt;
  This blog post is a written version of my presentation titled &amp;ldquo;Spock vs JUnit 5 - Clash of the Titans&amp;rdquo;. If you prefer, feel free to &lt;a href=&#34;https://speakerdeck.com/szpak/spock-vs-junit-5-clash-of-the-titans&#34;&gt;see the slides&lt;/a&gt; or &lt;a href=&#34;https://www.youtube.com/watch?v=aavtOBuzVcc&#34;&gt;watch the video&lt;/a&gt; instead.
&lt;/div&gt;
&lt;h2 id=&#34;historical-background&#34;&gt;Historical background&lt;/h2&gt;
&lt;p&gt;As a warm-up, let&amp;rsquo;s take a look at the important dates in the automatic code testing in Java.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2000 - JUnit - first xUnit for Java&lt;/li&gt;
&lt;li&gt;2004 - TestNG - Java 5 (annotations) leveraged in tests
&lt;ul&gt;
&lt;li&gt;with some unique (at the time) features (such as parameterized tests, test repetition or test dependency)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2006 - JUnit 4 - Java 5 support
&lt;ul&gt;
&lt;li&gt;catching up TestNG features over the next few years&lt;/li&gt;
&lt;li&gt;de facto standard (the world chose :-/ ), steady evolution rather than revolution&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2009 - Spock - revamped test creation
&lt;ul&gt;
&lt;li&gt;fresh ideas and power of Groovy under the hood&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2017 - JUnit 5 - redesigned and rewritten from scratch
&lt;ul&gt;
&lt;li&gt;new king of the hill? - let&amp;rsquo;s check it out!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;notices warning&#34; &gt;
  This comparison covers the latest released stable versions (as of April 2020) of JUnit (5.6) and Spock (1.3). I am fully aware of in-development &lt;a href=&#34;https://blog.solidsoft.pl/2020/01/02/migrating-spock-1.3-tests-to-spock-2.0/&#34;&gt;Spock 2.0&lt;/a&gt; and I plan to update this comparison (or write a supplement post) once 2.0-final is available.
&lt;/div&gt;
&lt;h2 id=&#34;development-comparison&#34;&gt;Development comparison&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start with a comparison of some biased aspects of development of JUnit 5 and Spock.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;JUnit 5 &lt;span class=&#34;table-smaller&#34;&gt;(as of 5.6)&lt;/span&gt;&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Spock &lt;span class=&#34;table-smaller&#34;&gt;(as of 1.3)&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;inception year&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2015&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;2009&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;number of GitHub stars&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3,7K&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;~2,6K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;number of commits&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;~6K&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;~2,5K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;development activity&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;high &lt;span class=&#34;table-smaller&#34;&gt;(young project)&lt;/span&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;medium &lt;span class=&#34;table-smaller&#34;&gt;(mature project)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;number of &lt;strong&gt;active&lt;/strong&gt; committers&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;1 + 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;number of contributors (ever)&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;~130&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;~80&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The first thing to notice is the fact that JUnit 5 is much younger project with very high development activity. There are 3 active committers with a bunch of external contributors.&lt;/p&gt;
&lt;p&gt;One the other hand, Spock is much more mature with lower development activity. However, many of the features developed in JUnit 5 recently were already available in Spock. Therefor, the need for lots of commit in Spock is lower. Spock has currently one main maintainer and 2-3 people regularly contributing to the project (of course also with a pack of external contributors).&lt;/p&gt;
&lt;h3 id=&#34;partial-verdict&#34;&gt;Partial verdict&lt;/h3&gt;
&lt;div class=&#34;alert alert-success&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;Development: &lt;strong&gt;JUnit 5 wins&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Reason: &lt;strong&gt;Mainly thanks to more active development activity in recent years.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id=&#34;tool-support&#34;&gt;Tool support&lt;/h2&gt;
&lt;p&gt;The next thing to cover is Java 11 compatibility and support in tools.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;JUnit 5&lt;/th&gt;
&lt;th align=&#34;right&#34;&gt;Spock&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Java 11+&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;very good&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;good &lt;span class=&#34;table-smaller&#34;&gt;(with modern Groovy 2.5.x)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IntelliJ IDEA&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;built-in&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;built-in &lt;span class=&#34;table-smaller&#34;&gt;(some Groovy limitations)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eclipse&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;build-in&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;built-in &lt;span class=&#34;table-smaller&#34;&gt;(some Groovy limitations)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netbeans&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;span style=&#34;color: orange&#34;&gt;10.0+ &lt;span class=&#34;table-smaller&#34;&gt;(Maven only)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;&lt;span style=&#34;color: orange&#34;&gt;unknown&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maven&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;plugin &lt;span class=&#34;table-smaller&#34;&gt;(official, Surefire)&lt;/span&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;plugin &lt;span class=&#34;table-smaller&#34;&gt;(GMavenPlus for Groovy)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gradle&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;built-in&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SonarQube&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;built-in&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;plugin &lt;span class=&#34;table-smaller&#34;&gt;(official for Groovy)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PIT - mutation testing&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;plugin &lt;span class=&#34;table-smaller&#34;&gt;(official)&lt;/span&gt;&lt;/td&gt;
&lt;td align=&#34;right&#34;&gt;build-in&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Both of the frameworks are currently very well supported in the Java ecosystem. However, it is worth to mention that tests (specifications) in Spock are written in Groovy (which notabene is the main power of Spock). As a downside, due to much more dynamic nature of Groovy as a language, IDEs have much harder time to provide as good support for it as for Java (e.g. refactoring or compile time error reporting).&lt;/p&gt;
&lt;p&gt;Regarding Java 11 and Spock, with modern Groovy 2.5.x it should work flawlessly. In general, most of the things should work fine also with Java 12, 13 and (with Groovy 2.5.10+) also 14. The official Java 14+ support should be available in Spock 2.0 (still in development) with Groovy 3.0.&lt;/p&gt;
&lt;p&gt;On the other hand, JUnit 5 is a role model on that field. It is continuously tested on a CI server with the recent Java versions (including the early access builds, such as OpenJDK 15 EA).&lt;/p&gt;
&lt;h3 id=&#34;partial-verdict-1&#34;&gt;Partial verdict&lt;/h3&gt;
&lt;div class=&#34;alert alert-success&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;Tool support: &lt;strong&gt;JUnit 5 wins&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Reason: &lt;strong&gt;Great IDE support for Java code and continuous testing with the bleeding edge versions of Java.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id=&#34;test-structure&#34;&gt;Test structure&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s move on to less technical aspects of test development - test structure.&lt;/p&gt;
&lt;p&gt;As die-hard followers of my blog may know, I am a big propagator of well structured automatic tests with the BDD-originated given-when-then concept. In short, it unifies test creation, improves their readability and makes it easier to write, especially for less experienced people. To learn more, please take a loot at a &lt;a href=&#34;https://solidsoft.wordpress.com/2017/05/16/importance-of-given-when-then-in-unit-tests-and-tdd/&#34; target=&#34;_blank&#34;&gt;separate blog post&lt;/a&gt;
 that I wrote some time ago.&lt;/p&gt;
&lt;h3 id=&#34;junit-5&#34;&gt;JUnit 5&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;SimpleCalculatorTest&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@Test&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shouldAddTwoNumbers&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;//given
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;n&#34;&gt;Calculator&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;calculator&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Calculator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;//when
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;calculator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;//then
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;n&#34;&gt;assertEquals&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The given-when-then sections are marked just by plain comments in code. It is not perfect. They might be forgotten and are easy to lost/misplace during refactoring. Could it be done better?&lt;/p&gt;
&lt;h3 id=&#34;spock&#34;&gt;Spock&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;SimpleCalculatorSpec&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;extends&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Specification&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should add two numbers&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;nl&#34;&gt;given:&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&#34;n&#34;&gt;Calculator&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;calculator&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Calculator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;nl&#34;&gt;when:&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;calculator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;nl&#34;&gt;then:&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Well, in Spock the (almost not used in Java) &lt;code&gt;label&lt;/code&gt; construction is leveraged. It is crucial to highlight that they are not just comments in code - they are a part of the specification. For example, having &lt;code&gt;when:&lt;/code&gt; removed in the example above, generates real compilation errors. Nice.&lt;/p&gt;
&lt;p&gt;Btw, of course, in Spock it is possible to write just one-liners, if feasible. However, developers have to do it intently.&lt;/p&gt;
&lt;h3 id=&#34;partial-verdict-2&#34;&gt;Partial verdict&lt;/h3&gt;
&lt;div class=&#34;alert alert-info&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;Test structure: &lt;strong&gt;Spock wins&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Reason: &lt;strong&gt;Spock cares more about well structured (and more readable) tests.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Btw, with both JUnit 5 and Spock it is worth to use &lt;a href=&#34;https://solidsoft.wordpress.com/2017/09/12/modern-tdd-oriented-java-8-junit-test-template-for-idea-with-mockito-and-assertj/&#34; target=&#34;_blank&#34;&gt;code templates&lt;/a&gt;
 to generate test skeleton to fill instead of writing all those given-when-then by hand :-).&lt;/p&gt;
&lt;h2 id=&#34;exception-testing&#34;&gt;Exception testing&lt;/h2&gt;
&lt;p&gt;Another topic I want to cover is exception testing. In general, to test corner cases (alternative scenarios) it is needed to verify that an exception with a given type was thrown. Usually, it is followed by some extra assertions such as an exception message and a cause.&lt;/p&gt;
&lt;h3 id=&#34;junit-5-1&#34;&gt;JUnit 5&lt;/h3&gt;
&lt;p&gt;In JUnit 5, it is no longer possible to use &lt;code&gt;@Test(expected = NullPointerException.class)&lt;/code&gt;, useful for one-liners, but potentially risky with more complicated test code. Instead of, we have the &lt;code&gt;assertThrows()&lt;/code&gt; construction, similar to &lt;code&gt;catchThrowable()&lt;/code&gt; from AssertJ.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Test&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shouldThrowBusinessExceptionOnCommunicationProblem&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;//when
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;Executable&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;sendPing&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TEST_REQUEST_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//then
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;CommunicationException&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;thrown&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;assertThrows&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CommunicationException&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;assertEquals&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Communication problem when sending request with id: &amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TEST_REQUEST_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;
                 &lt;span class=&#34;n&#34;&gt;thrown&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getMessage&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;());&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;assertEquals&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TEST_REQUEST_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;thrown&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getRequestId&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;());&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The syntax is very compact (thanks to the lambda expression which is used to catch an exception). In addition, it is easy to perform any required further assertion(s) on the returned exception instance.&lt;/p&gt;
&lt;h3 id=&#34;spock-1&#34;&gt;Spock&lt;/h3&gt;
&lt;p&gt;Spock, on the other hand, still provides &lt;code&gt;@FailsWith(NullPointerException)&lt;/code&gt; for one-liners. However, it is almost completely not used on a daily basis. All thanks to the &lt;code&gt;thrown()&lt;/code&gt; construction.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should capture exception&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nl&#34;&gt;when:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;sendPing&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TEST_REQUEST_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nl&#34;&gt;then:&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;CommunicationException&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;thrown&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Communication problem when sending request with id: $TEST_REQUEST_ID&amp;#34;&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;e&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;requestId&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TEST_REQUEST_ID&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It is worth to notice that there is no lambda expression to catch an exception. To implement that Spock leverages Groovy AST transformations which under the hood transparently add required code. As a result, the exception thrown in the &lt;code&gt;when&lt;/code&gt; block is caught and returned from the &lt;code&gt;thrown()&lt;/code&gt; method. Really smart.&lt;/p&gt;
&lt;p&gt;In addition, it is nice that in Spock, there is a smart type inference. It is not needed to precise the exception type twice. Based on the variable type on the left side, Spock is able to create the proper try-catch block.&lt;/p&gt;
&lt;p&gt;As a bonus, there as a separate utility class &lt;code&gt;Exceptions&lt;/code&gt; in Spock which provides extra assertions to play with the cause chain.&lt;/p&gt;
&lt;h3 id=&#34;partial-verdict-3&#34;&gt;Partial verdict&lt;/h3&gt;
&lt;div class=&#34;alert alert-info&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;Exception testing: &lt;strong&gt;Spock wins&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Reason: &lt;strong&gt;Even shorter and less intrusive mechanism for exception testing.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id=&#34;conditional-test-execution&#34;&gt;Conditional test execution&lt;/h2&gt;
&lt;p&gt;In multiple situation it is required to (not) execute a given test only if given condition is (not) met.&lt;/p&gt;
&lt;p&gt;The most common cases include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;particular Java version
&lt;ul&gt;
&lt;li&gt;reflection hack to use newer version features&lt;/li&gt;
&lt;li&gt;compatibility testing for lower version&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;specific operating system
&lt;ul&gt;
&lt;li&gt;notifications about changed files on Mac are much delayed&lt;/li&gt;
&lt;li&gt;testing symlinks on Windows makes no sense&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;tests executed only on CI server, stage environment, &amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;junit-5-2&#34;&gt;JUnit 5&lt;/h3&gt;
&lt;p&gt;JUnit 5 introduced brand new support for annotation-based &lt;code&gt;@Enabled*&lt;/code&gt; and &lt;code&gt;@Disabled*&lt;/code&gt; conditions.&lt;/p&gt;
&lt;p&gt;There is a predefined set of conditions for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JVM version&lt;/li&gt;
&lt;li&gt;operating system&lt;/li&gt;
&lt;li&gt;system property&lt;/li&gt;
&lt;li&gt;environment variable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Test&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@DisabledOnOs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;OS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;WINDOWS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shouldTestSymlinksBasedLogic&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@Test&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@EnabledIfSystemProperty&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;named&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;os.arch&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;matches&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;.*32.*&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shouldBeRunOn32BitSystems&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The JVM version and operating system conditions are enums and thanks to that, there is a nice code completion provided by an IDE. In addition the conditions can be used as meta-annotations to make more complex scenarios easier to use in multiple places.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Target&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ElementType&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;METHOD&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@Retention&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RetentionPolicy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;RUNTIME&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@Test&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@EnabledOnOs&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;WINDOWS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@EnabledIfSystemProperty&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;named&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;os.arch&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;matches&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;.*32.*&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;nd&#34;&gt;@interface&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;TestOn32BitWindows&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;With the following usage:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@TestOn32BitWindows&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shouldDoStrangeThings1OnLegacyWindows&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@TestOn32BitWindows&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shouldDoStrangeThings2OnLegacyWindows&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Originally, there was also support for custom logic in script-based inline conditions. However, due to limited usability (code written in &lt;code&gt;String&lt;/code&gt;) and deprecation of Nashorn in Java 11 it has been removed in JUnit 5.6. Writing own condition logic currently requires a custom implementation of &lt;code&gt;ExecutionCondition&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;spock-2&#34;&gt;Spock&lt;/h3&gt;
&lt;p&gt;Since time immemorial, Spock has provided support for annotation based conditions with &lt;code&gt;@Requires&lt;/code&gt; and &lt;code&gt;@IgnoreIf&lt;/code&gt;. Out of box it is possible to check:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JVM version&lt;/li&gt;
&lt;li&gt;operating system&lt;/li&gt;
&lt;li&gt;system property&lt;/li&gt;
&lt;li&gt;environment variable&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The same set implemented later on in JUnit 5. However, the usage is slightly different.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@IgnoreIf&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;jvm&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;java8Compatible&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;})&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should return empty Optional by default for unstubbed methods with Java 8+&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;nd&#34;&gt;@Requires&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sys&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;targetEnvironment&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;prod&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;})&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should execute smoke testing on non production environment&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Instead of enums, the logic is written in Groovy Closures leveraging delegation to the &lt;code&gt;jvm/os/sys/...&lt;/code&gt; objects providing a dedicated methods (such as &lt;code&gt;isJava11Compatible()&lt;/code&gt; or &lt;code&gt;isLinux()&lt;/code&gt;). Unfortunately there is no code completion available by default, but it can be enabled with a &lt;a href=&#34;https://speakerdeck.com/szpak/interesting-nooks-and-crannies-of-spock-you-may-have-never-seen-before?slide=27&#34; target=&#34;_blank&#34;&gt;small trick&lt;/a&gt;
 (Update. Just please be aware that the linked slides are from 2016 - Spock 1.0/1.1 - and in some places are outdated).&lt;/p&gt;
&lt;p&gt;Using Closures provides one more important benefit - custom logic can implemented inline with pure Groovy.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Requires&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;isStrongCryptographyEnabled&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;})&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//custom static method
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should test strong cryptography-based features&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;partial-verdict-4&#34;&gt;Partial verdict&lt;/h3&gt;
&lt;div class=&#34;alert alert-info&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;Conditional test execution: &lt;strong&gt;Spock wins&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Reason: &lt;strong&gt;Higher flexibility with non standard conditions.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id=&#34;mocking&#34;&gt;Mocking&lt;/h2&gt;
&lt;p&gt;Mocking is a crucial part of automatic code testing. It is especially beneficial in unit testing, but can be also usable in integration testing (e.g. with Spring Framework).&lt;/p&gt;
&lt;h3 id=&#34;junit-5-3&#34;&gt;JUnit 5&lt;/h3&gt;
&lt;p&gt;In JUnit 5 tests, Mockito is the first port of call when it comes to mocking.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Test&lt;/span&gt;
&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;should_not_call_remote_service_if_found_in_cache&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;//given
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;given&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cacheMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getCachedOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;willReturn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PLUS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//when
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;service&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;checkOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;//then
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;webserviceMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;should&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;never&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;checkOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;//   verify(webserviceMock, never()).checkOperator(CACHED_MOBILE_NUMBER);   //alternative syntax
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Mockito is an industrial standard for mocking in Java. It is very mature, well known with a rich set of features. In addition, Spring Boot provides the official support for injecting Mockito&amp;rsquo;s mocks and spies into its context, which can be very useful in integration tests.&lt;/p&gt;
&lt;h3 id=&#34;spock-3&#34;&gt;Spock&lt;/h3&gt;
&lt;p&gt;Spock on the other hand contains a built-in mocking subsystem.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should not hit remote service if found in cache&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nl&#34;&gt;given:&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;cacheMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getCachedOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PLUS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&#34;nl&#34;&gt;when:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;service&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;checkOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nl&#34;&gt;then:&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;webserviceMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;checkOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;While the syntax in Mockito is pretty readable, there are all those &lt;code&gt;given/thenReturn/thenAnswer/...&lt;/code&gt; to write. Spock, however, leverages the power of operator overloading in Groovy (and of course its AST transformations) to make stubbing and verification as simple as possible.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;n&#34;&gt;given&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cacheMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getCachedOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;willReturn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PLUS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;));&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;//Mockito
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// vs
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;cacheMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getCachedOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Optional&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;PLUS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;//Spock
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;verify&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;webserviceMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;never&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;checkOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;//Mockito
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// vs 
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;webserviceMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;checkOperator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;CACHED_MOBILE_NUMBER&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;//Spock
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;In a basic case, it&amp;rsquo;s enough to write a method, use an operator and provide a returned value. In verification it&amp;rsquo;s just a method call with requested cardinality. Most likely, it will not be possible to achieve that in Java in the predictable future.&lt;/p&gt;
&lt;p&gt;Historically, the main limitation with Spock&amp;rsquo;s mocks was their tight coupling with the specification (the test itself). As a result it was not possible to use Spock&amp;rsquo;s stubs, mocks and spies in the Spring context for integration tests. However, starting with Spock 1.1 it was relaxed and Spock 1.2 introduced the first class &lt;a href=&#34;https://solidsoft.wordpress.com/2018/09/03/spock-1-2-hassle-free-spring-beans-mocking-in-integration-tests/&#34; target=&#34;_blank&#34;&gt;support&lt;/a&gt;
 for mocking and spying with Spring. As a bonus, it is available also for pure Spring context (Spring Boot is not required as it takes place with Mockito&amp;rsquo;s mocks).&lt;/p&gt;
&lt;p&gt;To be fair, it is required to admit that more &lt;em&gt;magic&lt;/em&gt; in Spock generates some &lt;a href=&#34;https://speakerdeck.com/szpak/interesting-nooks-and-crannies-of-spock-you-may-have-never-seen-before&#34; target=&#34;_blank&#34;&gt;quirks&lt;/a&gt;
 with some corner cases. Nevertheless, once knowing all of them the readability and compactness definitely pay off :-).&lt;/p&gt;
&lt;p&gt;One more thing. It is worth to remember that with Spock used for testing, we are not forced to use it also for mocking. It is perfectly fine to use Mockito if wanted (or needed).&lt;/p&gt;
&lt;h3 id=&#34;partial-verdict-5&#34;&gt;Partial verdict&lt;/h3&gt;
&lt;div class=&#34;alert alert-info&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;Mocking: &lt;strong&gt;Spock wins&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Reason&lt;/strong&gt;: The syntax and really readable and compact. And with Spring support in Spock 1.2+ the last big limitation of the mocking subsystem in Spock was removed.&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id=&#34;parameterized-tests&#34;&gt;Parameterized tests&lt;/h2&gt;
&lt;p&gt;Parameterized tests in general provide a way to call one test with different set of input (and expected) parameters. It can dramatically reduce duplication in specific cases (e.g. in testing with the user defined acceptance data set).&lt;/p&gt;
&lt;p&gt;A word of warning here. In some scenarios, using parameterized tests can hide specific business use cases which would be clearly exposed in our non-parameterized tests otherwise. There are techniques to avoid that, but it is a topic for another article.&lt;/p&gt;
&lt;h3 id=&#34;junit-5-4&#34;&gt;JUnit 5&lt;/h3&gt;
&lt;p&gt;Parameterized tests were one of the key features of TestNG from its early days. In JUnit 4 the feature has been not available for year and even once implemented, the design made it very unpractical to use in most of the cases. To improve the situation the &lt;a href=&#34;https://github.com/Pragmatists/JUnitParams&#34; target=&#34;_blank&#34;&gt;3rd-party runners&lt;/a&gt;
 were available, but it was still sad (for JUnit 4).&lt;/p&gt;
&lt;p&gt;Luckily, JUnit 5 is the first version of JUnit with sane built-in parameterized tests support.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@ParameterizedTest&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@CsvSource&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;({&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;dog, 3&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;wolf, 4&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;hippopotamus , 12&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;testStringLengthWithParameterizedTestInJUnit5&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;word&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expectedNumberOfLetters&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;assertEquals&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;word&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expectedNumberOfLetters&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For simple scenario with inline values (provided as CSV strings), there is a nice implicit argument conversion from String for various types (e.g. dates, files, path or UUID). It just requires to add &lt;code&gt;@ParameterizedTest&lt;/code&gt; and &lt;code&gt;@CsvSource&lt;/code&gt; (or &lt;code&gt;@ValueSource&lt;/code&gt;, &lt;code&gt;@EnumSource&lt;/code&gt;, etc.).&lt;/p&gt;
&lt;p&gt;However, not everything can be put into string. The commonly encountered scenario is an object creation or calling a method defined in a test fixture. To support that JUnit 5 gives an ability to call a local method (or the one from external object) to return required input/output arguments. They should be provided as &lt;code&gt;Stream&lt;/code&gt; (or &lt;code&gt;List&lt;/code&gt;) of &lt;code&gt;Arguments&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@ParameterizedTest&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;value to pay for invoice {0} should be {1}&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@MethodSource&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;invoiceProvider&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shouldCalculateToPayValueForInvoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Invoice&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;invoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BigDecimal&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expectedValueToPay&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;//when
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;valueToPay&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;invoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toPayValue&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;//expect
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;assertEquals&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;expectedValueToPay&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;valueToPay&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;

&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Arguments&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;invoiceProvider&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Stream&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;Arguments&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;regularInvoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;54&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;Arguments&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;overduedInvoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;81&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;Arguments&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;of&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;paidInvoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It is just required to use &lt;code&gt;@MethodSource&lt;/code&gt; to point the method (or use a naming convention to resolve the correct method name automatically).&lt;/p&gt;
&lt;p&gt;The thing I don&amp;rsquo;t like is a lack of the arguments type check. In tests with multiple parameters it can be quite confusing to determine which is which.&lt;/p&gt;
&lt;p&gt;As a bonus it is also possible to customize a test name which will be displayed in the report (in IDE, HTML report, etc.).&lt;/p&gt;
&lt;h3 id=&#34;spock-4&#34;&gt;Spock&lt;/h3&gt;
&lt;p&gt;In Spock, first let&amp;rsquo;s take a longer look at the simple parameterized test.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Unroll&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should sum two integers (#x + #y = #expectedResult)&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&#34;nl&#34;&gt;when:&lt;/span&gt;
        &lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;calculator&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nl&#34;&gt;then:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expectedResult&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;    &lt;span class=&#34;nl&#34;&gt;where:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;         &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;  &lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expectedResult&lt;/span&gt;
&lt;/span&gt;         &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;  &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The words that come to my mind are &amp;ldquo;state of the art&amp;rdquo;. This is a place where Spocks excels.&lt;/p&gt;
&lt;p&gt;With table-like formatting after the &lt;code&gt;where&lt;/code&gt; keyword, input data looks very natural and is easy to read. What is worth mentioning, there is no need to define &lt;code&gt;x, y, expectedResult&lt;/code&gt; as method arguments in a test (as it takes place in JUnit 5). The variables are added implicitly with full visibility and type inference in IDE.&lt;/p&gt;
&lt;p&gt;The method name can be parameterized inline with the &lt;code&gt;#var&lt;/code&gt; syntax (it&amp;rsquo;s Groovy - methods can have spaces and other &amp;ldquo;strange&amp;rdquo; characters).&lt;/p&gt;
&lt;p&gt;In Spock it is also not a problem to use table-like syntax in a situation where constructor or methods are needed to be called (which in JUnit 5 requires using a separate provider method).&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Unroll&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Value to pay for invoice #invoice should be #expectedValueToPay&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should calculate value to pay for invoice&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nl&#34;&gt;expect:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;invoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;valueToPay&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expectedValueToPay&lt;/span&gt;
    &lt;span class=&#34;nl&#34;&gt;where:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;invoice&lt;/span&gt;           &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expectedValueToPay&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;regularInvoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;  &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;54&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&#34;n&#34;&gt;overduedInvoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;81&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;paidInvoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;While working with acceptance testing where results are presented to less technical users, it is also possible to distinguish a test name for developers with a scenario name for QA engineers (or product owners) by writing it in the &lt;code&gt;@Unroll&lt;/code&gt; annotation.&lt;/p&gt;
&lt;p&gt;Of course, for more complex/advanced use cases (e.g. generating input parameters dynamically based on exterenal source), data pipes and data providers can be used. They are not as natural as the aforementioned table, but are very powerful.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Unroll&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;#pesel is valid (#dbId)&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should validate PESEL correctness (CSV)&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;nl&#34;&gt;expect:&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;sut&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;validate&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pesel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;nl&#34;&gt;where:&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;        &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;dbId&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pesel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;readValidPeopleFromCSVFile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;                                   &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;readLines&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;collect&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;it&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;                                   &lt;span class=&#34;c1&#34;&gt;//ugly way to read CSV - don&amp;#39;t do this :-)
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;partial-verdict-6&#34;&gt;Partial verdict&lt;/h3&gt;
&lt;div class=&#34;alert alert-info&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;Parameterized tests: &lt;strong&gt;Spock wins&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Reason: &lt;strong&gt;It is enough to visually compare parameterized tests in those two frameworks.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;h2 id=&#34;migration&#34;&gt;Migration&lt;/h2&gt;
&lt;p&gt;The next point is very important for people currently using JUnit 4.&lt;/p&gt;
&lt;h3 id=&#34;junit-4--junit-5&#34;&gt;JUnit 4 → JUnit 5&lt;/h3&gt;
&lt;p&gt;The JUnit 5 tests can co-exist with the JUnit 4 tests. There is a dedicated module &lt;code&gt;junit5-vintage&lt;/code&gt; which executes old JUnit 4 tests on the new JUnit Platform (part of JUnit 5).&lt;/p&gt;
&lt;p&gt;Writing new tests with JUnit 5 is also easy. The test structure is very similar. We just need to learn some new keywords, annotations and assertions (and remember to use &lt;code&gt;@Test&lt;/code&gt; from the new &lt;code&gt;org.junit.jupiter.api&lt;/code&gt; package :-) ).&lt;/p&gt;
&lt;h3 id=&#34;junit-4--spock&#34;&gt;JUnit 4 → Spock&lt;/h3&gt;
&lt;p&gt;The Spock tests can also co-exists with the JUnit 4 tests. In fact Spock 1.x is a (sophisticated, but still) JUnit 4 runner. However, besides that there is a completely new test structure which we need to get familiar with. It is easy to grasp and, in the end, it is more readable, but still, it is something new to learn.&lt;/p&gt;
&lt;h3 id=&#34;partial-verdict-7&#34;&gt;Partial verdict&lt;/h3&gt;
&lt;div class=&#34;alert alert-success&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;Tool support: &lt;strong&gt;JUnit 5 wins&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Reason: &lt;strong&gt;The JUnit 5 tests are more similar to the JUnit 4 tests and therefor, that migration path should be a little bit easier.&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;One more important migration-related thing here. During my &lt;a href=&#34;https://blog.solidsoft.pl/training/&#34;&gt;training or consulting&lt;/a&gt;
, I do not recommend rewriting existing hundreds and thousands of tests from JUnit 4 to the new technology, just for fun. Most of the existing tests will stay untouched for the foreseeable future. It is much better to write the new tests in the new technology and rewrite existing tests only along the way of doing some production logic related changes in them.&lt;/p&gt;
&lt;h3 id=&#34;summary---final-verdict&#34;&gt;Summary - final verdict&lt;/h3&gt;
&lt;p&gt;Inarguably, JUnit 5 is a great progress over JUnit 4. Many features (previously) unique to Spock now are available in JUnit 5. However, Spock still excels in some areas. The best choice is no longer obvious.&lt;/p&gt;
&lt;p&gt;Here, an anecdote, proposed my a colleague of mine. There are BMW and Audi cars. Both brands are very good and the choice usually depends on our personal preferences.&lt;/p&gt;
&lt;p&gt;There same with Spock and JUnit 5. First, let&amp;rsquo;s take a look at the features comparison of the presented testing frameworks.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;JUnit 5 &lt;span class=&#34;table-smaller&#34;&gt;(as of 5.6)&lt;/span&gt;&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Spock &lt;span class=&#34;table-smaller&#34;&gt;(as of 1.3)&lt;/span&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;development&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;span style=&#34;color: green&#34;&gt;very good&lt;/span&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good &lt;span class=&#34;table-smaller&#34;&gt;(new features and bugfixes)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;learning curve&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;span style=&#34;color: green&#34;&gt;very good&lt;/span&gt; &lt;span class=&#34;table-smaller&#34;&gt;(similar to 4)&lt;/span&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good &lt;span class=&#34;table-smaller&#34;&gt;(Groovy to grasp)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tool support&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;span style=&#34;color: green&#34;&gt;very good&lt;/span&gt; &lt;span class=&#34;table-smaller&#34;&gt;(trending up)&lt;/span&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good &lt;span class=&#34;table-smaller&#34;&gt;(weaker compile time checks)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;test structure&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;span style=&#34;color: green&#34;&gt;very good&lt;/span&gt; &lt;span class=&#34;table-smaller&#34;&gt;(BDD by default)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;exception testing&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;span style=&#34;color: green&#34;&gt;very good&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;conditional test execution&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;span style=&#34;color: green&#34;&gt;very good&lt;/span&gt; &lt;span class=&#34;table-smaller&#34;&gt;(custom logic)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mocking&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good &lt;span class=&#34;table-smaller&#34;&gt;(Mockito)&lt;/span&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good+ &lt;span class=&#34;table-smaller&#34;&gt;(very compact, some quirks)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;parameterized tests&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;span style=&#34;color: green&#34;&gt;&lt;strong&gt;very good&lt;/strong&gt;&lt;/span&gt; &lt;span class=&#34;table-smaller&#34;&gt;(exceptional!)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;migration from JUnit 4&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;span style=&#34;color: green&#34;&gt;very good&lt;/span&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;good&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;As you see, they both have their strengths and weaknesses. In addition to covered aspects, you should add to that list other aspects which are important for you (and for your team) and see which framework fits you more.&lt;/p&gt;
&lt;p&gt;For instance.&lt;/p&gt;
&lt;div class=&#34;alert alert-warning&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;If you prefer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;old good Java as the only language&lt;/li&gt;
&lt;li&gt;stability and being mainstream&lt;/li&gt;
&lt;li&gt;stronger compile time error checking&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;you should choose &lt;strong&gt;JUnit 5&lt;/strong&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;On the other hand,&lt;/p&gt;
&lt;div class=&#34;alert alert-info&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;if - like me - you favor:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;simplicity and readability&lt;/li&gt;
&lt;li&gt;power of Groovy under the hood&lt;/li&gt;
&lt;li&gt;beautiful parameterized tests and exception testing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span class=&#34;alert-bigger&#34;&gt;then &lt;strong&gt;Spock&lt;/strong&gt; should be better for you.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;One final reflection. Preparing my presentation (and later on that blog post), I realized it would be great to have only that kind of dilemma while crafting software, choose between two pieces of good software :-).&lt;/p&gt;
&lt;span style=&#34;opacity: 0.6&#34;&gt;A note about Spock logo. As of earthdate 2020-04, Spock doesn&amp;rsquo;t have the official logo. The one used in the lead photo is a proposal by &lt;a href=&#34;https://github.com/sbglasius&#34;&gt;Søren Berg Glasius&lt;/a&gt; made back in 2014. There are also &lt;a href=&#34;https://github.com/spockframework/spock/pull/34#issuecomment-586403638&#34;&gt;some&lt;/a&gt; other &lt;a href=&#34;https://github.com/spockframework/spock/pull/34#issuecomment-592687040&#34;&gt;proposals&lt;/a&gt;, but if you have a good idea, feel free to propose it &lt;a href=&#34;https://github.com/spockframework/spock/pull/34&#34;&gt;there&lt;/a&gt; (or vote for existing candidates).&lt;/span&gt;
</content:encoded>
        <dc:creator>Marcin Zajączkowski</dc:creator>
        <media:content url="https://blog.solidsoft.pl/images/posts/2020/spock-vs-junit5-ratio.png" medium="image"><media:title type="html">featured image</media:title></media:content>
        
        <media:content url="https://blog.solidsoft.pl/images/posts/2020/spock-vs-junit5-ratio.png" medium="image"><media:title type="html">meta image</media:title></media:content>
        
          
            
              <category>spock</category>
            
          
            
              <category>junit5</category>
            
          
            
              <category>testing</category>
            
          
            
              <category>java</category>
            
          
            
              <category>groovy</category>
            
          
            
              <category>presentation</category>
            
          
            
              <category>comparison</category>
            
          
        
        
          
            
              <category>Tools</category>
            
          
            
              <category>Deep Dive</category>
            
          
        
        
      </item>
      
      <item>
        <title>Mysteriously broken reduction operation on parallel streams in Java (explained)</title>
        <link>https://blog.solidsoft.pl/2020/03/12/mysteriously-broken-reduction-operation-on-parallel-streams-in-java-explained/</link>
        <pubDate>Thu, 12 Mar 2020 14:00:00 +0200</pubDate>
        
        <atom:modified>Thu, 12 Mar 2020 14:00:00 +0200</atom:modified>
        <guid>https://blog.solidsoft.pl/2020/03/12/mysteriously-broken-reduction-operation-on-parallel-streams-in-java-explained/</guid>
        <description>How to not get into trouble writing custom reduction operation (.reduce()) on (parallel) streams with Java 8+ (including Java 14).
  Introduction Recently&amp;hellip;, well this article has spent years in my freezer for the blog posts. Originally, I have encountered this problem back in 2014 while preparing my Java 8 training session (recently renamed to Java - functional thinking ). Then, I noticed that it is possible to achieve interesting results writing a custom reduce operation implementation when a parallel stream is used.</description>
        <content:encoded>&lt;blockquote&gt;
&lt;p&gt;How to not get into trouble writing custom reduction operation (&lt;code&gt;.reduce()&lt;/code&gt;) on (parallel) streams with Java 8+ (including Java 14).&lt;/p&gt;
&lt;/blockquote&gt;


&lt;figure &gt;
  
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2020/java8-reduce-issue-parallel-stream.jpg&#34; alt=&#34;5 parallel streams of waterfall&#34; style=&#34;width:;height:;&#34;/&gt;
  
  
&lt;/figure&gt;

&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Recently&amp;hellip;, well this article has spent years in my freezer for the blog posts. Originally, I have encountered this problem back in 2014 while preparing my Java 8 training session (recently renamed to &lt;a href=&#34;https://blog.solidsoft.pl/training/&#34;&gt;Java - functional thinking&lt;/a&gt;
). Then, I noticed that it is possible to achieve interesting results writing a custom &lt;code&gt;reduce&lt;/code&gt; operation implementation when a parallel stream is used. For various reasons, the partially written article was waiting for its completion around 6 years. Time flies, however, the case is still valid with the latest - as a time of writing - Java 14. So, let&amp;rsquo;s check it out.&lt;/p&gt;
&lt;h2 id=&#34;our-case---simple-number-concatenation-using-reduce&#34;&gt;Our case - simple number concatenation using reduce&lt;/h2&gt;
&lt;p&gt;As a short introduction, a &lt;em&gt;reduction operation&lt;/em&gt; (also called a &lt;em&gt;fold&lt;/em&gt;) takes input elements (here of a stream) and collects them into combined summary result. Some well know specialized reduction variants, available in the Stream API, include, inter alia, &lt;code&gt;sum()&lt;/code&gt;, &lt;code&gt;min()&lt;/code&gt; and &lt;code&gt;count()&lt;/code&gt;. Nevertheless, we can write our custom, non-standard reduction operation (if needed).&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s assume we would like to concatenate a list of numbers into a string. A case which could be easier to achieve in other ways, but simple enough to do not focus on realized logic, but rather a nuances of a reduction operation itself. A &lt;code&gt;reduce&lt;/code&gt; method on stream can be used:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Test&lt;/span&gt;
&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shouldConcatNumbersUsingReduce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;c1&#34;&gt;//given
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kd&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Integer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arrays&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;asList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;//when
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;kd&#34;&gt;final&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;stream&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;            &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;reduce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;                    &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;//then
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;assertThat&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;isEqualToIgnoringCase&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1234&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;//passes
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Very compact and does its work. Numbers are concatenated. Similar implementations are common in internet and everything is ok unless you try to use it with the parallel stream:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@Test&lt;/span&gt;
&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;shouldConcatNumbersUsingReduceParallel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;//broken!
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//given
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Integer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Arrays&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;asList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;//when
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;parallelStream&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;reduce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt;
                    &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt;
                    &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
            &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;//then
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;n&#34;&gt;assertThat&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;result&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;isEqualToIgnoringCase&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1234&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;//ups!
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This test fails with the assertion error similar to that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;n&#34;&gt;java&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;lang&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;AssertionError&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; 
&lt;span class=&#34;nl&#34;&gt;Expecting:&lt;/span&gt;
 &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;343421343421343421343421&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;to&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;be&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;equal&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;to&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;
 &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;1234&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It looks strange. Very often incomprehensible things are caused by some race condition in the parallel code which matches &lt;code&gt;parallelStream()&lt;/code&gt;. But first let&amp;rsquo;s analyze what happens in a reduction operation step by step (if you are savvy in sequential reduction operations skip to the subsequent section).&lt;/p&gt;
&lt;h2 id=&#34;reduction-in-sequential-stream&#34;&gt;Reduction in sequential stream&lt;/h2&gt;
&lt;p&gt;If you are not very familiar with method references the example can look a little bit cryptic. Let&amp;rsquo;s rewrite it using lambda expressions (instead method references):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;stream&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;reduce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt;
                &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;//accumulation
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;                &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;))&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;//combining
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The new &lt;code&gt;StringBuilder&lt;/code&gt; is used as an initial value (identity). For every element from an input list the second line in reduce will be called (&lt;code&gt;(acc, x) -&amp;gt; acc.append(x)&lt;/code&gt;) with &lt;code&gt;acc&lt;/code&gt; (an accumulator) containing concatenated already processed elements and &lt;code&gt;x&lt;/code&gt; the current number. &lt;code&gt;x&lt;/code&gt; is appended to the previously concatenated elements.&lt;/p&gt;
&lt;p&gt;From the algorithm analysis, the expected values in subsequent iterations should be as follows:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;iteration&lt;/th&gt;
&lt;th align=&#34;center&#34;&gt;0&lt;/th&gt;
&lt;th align=&#34;center&#34;&gt;1&lt;/th&gt;
&lt;th align=&#34;center&#34;&gt;2&lt;/th&gt;
&lt;th align=&#34;center&#34;&gt;3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;acc&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&amp;quot;&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&amp;ldquo;1&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&amp;ldquo;12&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&amp;ldquo;123&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;x&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;1&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;2&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;3&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;returned&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&amp;ldquo;1&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&amp;ldquo;12&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&amp;ldquo;123&amp;rdquo;&lt;/td&gt;
&lt;td align=&#34;center&#34;&gt;&amp;ldquo;1234&amp;rdquo;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Is this ok? Let&amp;rsquo;s verify it in code.&lt;/p&gt;
&lt;p&gt;As debugging (prospectively) concurrent code is hard, especially in a blog post, let&amp;rsquo;s use plain old debug outputs, well known from C.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;stream&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;reduce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;accString&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Accumulation: &amp;#39;{}&amp;#39;, x: &amp;#39;{}&amp;#39;, returned: &amp;#39;{}&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;accString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt; 
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;                                     &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1String&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Combining: sb1: &amp;#39;{}&amp;#39;, sb2: &amp;#39;{}&amp;#39;, returned: &amp;#39;{}&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;                                 &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;));&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;})&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;We slightly complicated the code, but it is only for the test (debug) purpose. The output is as expected:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;18:09:05.839 [main] - Accumulation: acc: &amp;#39;    &amp;#39;, x: &amp;#39;   1&amp;#39;, returned: &amp;#39;   1&amp;#39;
18:09:05.844 [main] - Accumulation: acc: &amp;#39;   1&amp;#39;, x: &amp;#39;   2&amp;#39;, returned: &amp;#39;  12&amp;#39;
18:09:05.844 [main] - Accumulation: acc: &amp;#39;  12&amp;#39;, x: &amp;#39;   3&amp;#39;, returned: &amp;#39; 123&amp;#39;
18:09:05.844 [main] - Accumulation: acc: &amp;#39; 123&amp;#39;, x: &amp;#39;   4&amp;#39;, returned: &amp;#39;1234&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s skip for a while the log from the combining operation (line 14). It is not used in sequential streams.&lt;/p&gt;
&lt;p&gt;In the output, we also clearly see that all operations take place in the main thread. Which is expected for sequential synchronous stream processing.&lt;/p&gt;
&lt;h2 id=&#34;reduction-in-parallel-stream---behavior-in-working-implementation&#34;&gt;Reduction in parallel stream - behavior in working implementation&lt;/h2&gt;
&lt;p&gt;In a parallel stream, accumulation operations can be performed in different threads. Those partial results are later combined using lambda expression passed as the third argument (a combiner) in a &lt;code&gt;reduce&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at the diagnostic messages emitted during a sample execution with parallel stream.&lt;/p&gt;
&lt;div class=&#34;alert alert-warning&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;One important note here. The output is from the correctly implemented reduction operation (presented at the end of the blog post) rather than the version above to make the whole thing easier to grasp.&lt;/div&gt;

&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;[ForkJoinPool.commonPool-worker-3] - Accumulation: acc: &amp;#39;    &amp;#39;, x:   &amp;#39;   1&amp;#39;, returned: &amp;#39;   1&amp;#39;
[ForkJoinPool.commonPool-worker-1] - Accumulation: acc: &amp;#39;    &amp;#39;, x:   &amp;#39;   2&amp;#39;, returned: &amp;#39;   2&amp;#39;
[main]                             - Accumulation: acc: &amp;#39;    &amp;#39;, x:   &amp;#39;   3&amp;#39;, returned: &amp;#39;   3&amp;#39;
[ForkJoinPool.commonPool-worker-1] - Combining   : sb1: &amp;#39;   1&amp;#39;, sb2: &amp;#39;   2&amp;#39;, returned: &amp;#39;  12&amp;#39;
[ForkJoinPool.commonPool-worker-2] - Accumulation: acc: &amp;#39;    &amp;#39;, x:   &amp;#39;   4&amp;#39;, returned: &amp;#39;   4&amp;#39;
[ForkJoinPool.commonPool-worker-2] - Combining   : sb1: &amp;#39;   3&amp;#39;, sb2: &amp;#39;   4&amp;#39;, returned: &amp;#39;  34&amp;#39;
[ForkJoinPool.commonPool-worker-2] - Combining   : sb1: &amp;#39;  12&amp;#39;, sb2: &amp;#39;  34&amp;#39;, returned: &amp;#39;1234&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Let&amp;rsquo;s analyze it line by line.&lt;/p&gt;
&lt;p&gt;In the first 2 lines:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;[ForkJoinPool.commonPool-worker-3] - Accumulation: acc: &amp;#39;    &amp;#39;, x:   &amp;#39;   1&amp;#39;, returned: &amp;#39;   1&amp;#39;
[ForkJoinPool.commonPool-worker-1] - Accumulation: acc: &amp;#39;    &amp;#39;, x:   &amp;#39;   2&amp;#39;, returned: &amp;#39;   2&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;the accumulation operation is performed in parallel on the two first elements on the list. In the forth line those partial results are combined into a larger list:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;[ForkJoinPool.commonPool-worker-1] - Combining   : sb1: &amp;#39;   1&amp;#39;, sb2: &amp;#39;   2&amp;#39;, returned: &amp;#39;  12&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The same situation, for the rest of the items, takes place in the line 3, 5 and 6.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;[main]                             - Accumulation: acc: &amp;#39;    &amp;#39;, x:   &amp;#39;   3&amp;#39;, returned: &amp;#39;   3&amp;#39;
...
[ForkJoinPool.commonPool-worker-2] - Accumulation: acc: &amp;#39;    &amp;#39;, x:   &amp;#39;   4&amp;#39;, returned: &amp;#39;   4&amp;#39;
[ForkJoinPool.commonPool-worker-2] - Combining   : sb1: &amp;#39;   3&amp;#39;, sb2: &amp;#39;   4&amp;#39;, returned: &amp;#39;  34&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;And the end, two partial result: &amp;lsquo;12&amp;rsquo; and &amp;lsquo;34&amp;rsquo; are combined together to provide the final result:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;[ForkJoinPool.commonPool-worker-2] - Combining   : sb1: &amp;#39;  12&amp;#39;, sb2: &amp;#39;  34&amp;#39;, returned: &amp;#39;1234&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Do you have - after logging at the listings - any suspicious what could be wrong with the original implementation? With the debug statements it much easier to spot it.&lt;/p&gt;
&lt;h2 id=&#34;reduction-in-parallel-stream-with-widespread-broken-implementation&#34;&gt;Reduction in parallel stream with widespread (broken) implementation&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s recall the widespread (broken when running in parallel) implementation once more:&lt;/p&gt;
&lt;div class=&#34;expand&#34;&gt;
  &lt;button type=&#34;button&#34; class=&#34;expand__button&#34; aria-label=&#34;Expand Button&#34;&gt;
    &lt;span class=&#34;expand-icon expand-icon__right&#34;&gt;
        &lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;24&#34; height=&#34;24&#34; viewBox=&#34;0 0 24 24&#34;&gt;&lt;path fill=&#34;currentColor&#34; d=&#34;M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z&#34;/&gt;&lt;/svg&gt;
    &lt;/span&gt;
    click to expand
  &lt;/button&gt;
  &lt;div class=&#34;expand__content&#34;&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;parallelStream&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;reduce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt;
                &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt;      &lt;span class=&#34;c1&#34;&gt;//accumulation
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;                &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;))&lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;//combining
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;together with its debug enhanced variant:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;parallelStream&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;reduce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;accString&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&#34;n&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Accumulation: &amp;#39;{}&amp;#39;, x: &amp;#39;{}&amp;#39;, returned: &amp;#39;{}&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;accString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt; 
                                     &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;));&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;},&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1String&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&#34;n&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;info&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;Combining: sb1: &amp;#39;{}&amp;#39;, sb2: &amp;#39;{}&amp;#39;, returned: &amp;#39;{}&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb1String&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt;
                                 &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%4s&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;));&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ret&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;})&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The output from the parallel processing execution:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;10:42:53.334 [ForkJoinPool.commonPool-worker-5]  - Accumulation: acc: &amp;#39;   3&amp;#39;, x: &amp;#39;   4&amp;#39;, returned: &amp;#39;  34&amp;#39;
10:42:53.334 [ForkJoinPool.commonPool-worker-23] - Accumulation: acc: &amp;#39; 342&amp;#39;, x: &amp;#39;   1&amp;#39;, returned: &amp;#39;3421&amp;#39;
10:42:53.334 [ForkJoinPool.commonPool-worker-19] - Accumulation: acc :&amp;#39;  34&amp;#39;, x: &amp;#39;   2&amp;#39;, returned: &amp;#39;3421&amp;#39;
10:42:53.334 [main]                              - Accumulation: acc :&amp;#39;    &amp;#39;, x: &amp;#39;   3&amp;#39;, returned: &amp;#39;   3&amp;#39;
10:42:53.339 [ForkJoinPool.commonPool-worker-19] - Combining: sb1: &amp;#39;3421&amp;#39;, sb2: &amp;#39;342134213421&amp;#39;, returned: &amp;#39;342134213421&amp;#39;
10:42:53.339 [main]                              - Combining: sb1: &amp;#39;3421&amp;#39;, sb2: &amp;#39;342134213421&amp;#39;, returned: &amp;#39;342134213421&amp;#39;
10:42:53.340 [main]                              - Combining: sb1: &amp;#39;342134213421&amp;#39;, sb2: &amp;#39;342134213421342134213421&amp;#39;, returned: &amp;#39;342134213421342134213421&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The strange things start to happen from the first line. Instead of having an empty accumulator (the &amp;ldquo;acc&amp;rdquo; variable) there is &amp;ldquo;3&amp;rdquo;. In the second line there is already &amp;ldquo;342&amp;rdquo; (still instead of an empty StringBuilder). We discover empty accumulator in the 3rd line, which anyway could be the 1st line (it is a matter of logging operations from multiple threads - they were executed at &amp;ldquo;the same moment&amp;rdquo;). Nonetheless, all the first 4 lines should have the accumulator empty. It clearly shows there is a problem with a mutable data structure shared across the threads, in both accumulation and combining phrases.&lt;/p&gt;
&lt;p&gt;A look at the &lt;code&gt;StringBuilder&lt;/code&gt; documentation ensures us that &amp;ldquo;append&amp;rdquo; adds a provided value to the &lt;code&gt;StringBuilder&lt;/code&gt; and returns its instance (aka &lt;code&gt;this&lt;/code&gt;). Mutating input variables is not recommended in the stream processing, however the root of the problem is a fact that initial &amp;ldquo;neutral&amp;rdquo; value (identity) passes to every initial accumulation operation is one and the same &lt;code&gt;StringBuilder&lt;/code&gt; instance. It is passed as the first element of the &amp;ldquo;reduce&amp;rdquo; method execution.&lt;/p&gt;
&lt;p&gt;Someone could say: &amp;ldquo;let&amp;rsquo;s use &lt;code&gt;StringBuffer&lt;/code&gt; - its operations are thread safe&amp;rdquo;. However, it will not fix the situation here. Having multiple threads operating on the same structure (even thread safe) is also broken assuming that all initial operations assumes a private accumulator instance to create an independent list of elements which will be concatenated into the biggest one in the following steps.&lt;/p&gt;
&lt;h2 id=&#34;reduction-in-parallel-stream---working-implementation&#34;&gt;Reduction in parallel stream - working implementation&lt;/h2&gt;
&lt;h3 id=&#34;main-case&#34;&gt;Main case&lt;/h3&gt;
&lt;p&gt;With &lt;code&gt;StringBuffer&lt;/code&gt; and string concatenation the only required modification is not mutating the input objects:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;n&#34;&gt;String&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;result&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;parallelStream&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;()&lt;/span&gt;
        &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;reduce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt;
&lt;span class=&#34;hl&#34;&gt;                &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;acc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#34;hl&#34;&gt;                &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;StringBuilder&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;append&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sb2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;toString&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;In every iteration the new &lt;code&gt;StringBuilder&lt;/code&gt; instance is created. Thanks to that there is no mutation of the initial &lt;code&gt;identity&lt;/code&gt; element shared across threads. In general mutation of the stream elements (or doing side effects in general) can lead to some unpredictable situations, especially in the parallel execution.&lt;/p&gt;
&lt;h3 id=&#34;java-api-limitations&#34;&gt;Java API limitations&lt;/h3&gt;
&lt;p&gt;The above change solves the problem (at the cost of greatly increased number of created objects, but let&amp;rsquo;s skip it for a moment). Unfortunately, many structures, especially those from Java Collection Framework which remembers Java 1.2 (releases 1998 - over 20 years ago!), does not provide so friendly API to perform operations with the method chaining syntax/approach.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a look at the (artificial) working example of using the &lt;code&gt;java.util.List&lt;/code&gt; API in a reduce operation simulating mapping to double every element of the input list:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Integer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;doubledValues&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stream&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;reduce&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Collections&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;emptyList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(),&lt;/span&gt;
            &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Integer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;resultList&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ArrayList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;resultList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;resultList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;
            &lt;span class=&#34;o&#34;&gt;},&lt;/span&gt;
            &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;list1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;list2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;List&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Integer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;resultList&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ArrayList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;list1&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;resultList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;addAll&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;list2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;);&lt;/span&gt;
                &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;resultList&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;
            &lt;span class=&#34;o&#34;&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;True one-liners with a method chaining would make this code more readable.&lt;/p&gt;
&lt;div class=&#34;alert alert-warning&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;Please note that the aforementioned logic (doubling list elements) can be implemented easily in native operations available in Java 8+. However, the reduce operation has its own usages and that example emphatically depicts and limitation of the collection API.&lt;/div&gt;

&lt;h3 id=&#34;immutable-collections&#34;&gt;Immutable collections&lt;/h3&gt;
&lt;p&gt;In addition to more verbose syntax, Java collections are in general mutable. This makes it harder (more error prone) to use them in (to share the instance between) multiple threads. &lt;a href=&#34;https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/concurrent/package-summary.html&#34; target=&#34;_blank&#34;&gt;Thread safety&lt;/a&gt;
 for collections might help, but as I already mentioned in that case it will not (as the initial empty collection is distributed across diffrent threads). However, in some more functional languages such as Scala, not to mention Haskel, it is quite popular to use immutable collections.&lt;/p&gt;
&lt;p&gt;They typically has the &amp;ldquo;first&amp;rdquo; element, called head and the rest called tail. Adding a new element before head is cheap as the new head can share the old one as tail (which is immutable, remember?). Of course, in some other use cases (such as putting elements between other elements) they cannot keep up with a classic mutable counterparts. and it can be used in different use cases. Nevertheless, it might be an alternative worth consideration. For Java, there is - among others - the &lt;a href=&#34;https://www.vavr.io/vavr-docs/#_data_structures_in_a_nutshell&#34; target=&#34;_blank&#34;&gt;collections API in Vavr&lt;/a&gt;
.&lt;/p&gt;
&lt;h3 id=&#34;mutable-reduction-operation&#34;&gt;Mutable reduction operation&lt;/h3&gt;
&lt;p&gt;To deal with cases where mutable operation are much more memory/CPU effective a dedicated Collector can be written which realizes &lt;a href=&#34;https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#MutableReduction&#34; target=&#34;_blank&#34;&gt;mutable reduction operation&lt;/a&gt;
. More info about writing a custom &lt;code&gt;Collector&lt;/code&gt; can be found in this interesting &lt;a href=&#34;https://www.nurkiewicz.com/2014/07/introduction-to-writing-custom.html&#34; target=&#34;_blank&#34;&gt;blog post&lt;/a&gt;
 by Tomasz Nurkiewicz.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I hope that you were hard enough to get with me to the end of this (quite long and quite low level) blog post :-).&lt;/p&gt;
&lt;p&gt;Using this example with reduce, I wanted to show one of the possible problems while dealing with parallel execution and its explaination. It is not a bug in JDK, but rather a presumption in the (parallel) stream API which - as I observe during my &lt;a href=&#34;https://blog.solidsoft.pl/training/&#34;&gt;testing classes&lt;/a&gt;
 - are not emphasised enough to be common knowledge. It is good to know your tools and use it properly, as well as extend ones awareness about new and alternative solutions. And remember, state mutation is problematic. Prefer immutable data structures if only possible (and feasible).&lt;/p&gt;
&lt;span style=&#34;opacity: 0.6&#34;&gt;Lead photo by &lt;a href=&#34;https://pixabay.com/users/free-photos-242387/&#34;&gt;Free-Photos&lt;/a&gt;, published in &lt;a href=&#34;https://pixabay.com/photos/waterfall-rocks-trees-forest-woods-802003/&#34;&gt;Pixabay&lt;/a&gt;, Pixabay License.&lt;/span&gt;
</content:encoded>
        <dc:creator>Marcin Zajączkowski</dc:creator>
        <media:content url="https://blog.solidsoft.pl//images/posts/2020/java8-reduce-issue-parallel-stream-thumbnail.jpg" medium="image"><media:title type="html">featured image</media:title></media:content>
        
        <media:content url="https://blog.solidsoft.pl//images/posts/2020/java8-reduce-issue-parallel-stream-ratio.jpg" medium="image"><media:title type="html">meta image</media:title></media:content>
        
          
            
              <category>java</category>
            
          
            
              <category>java8</category>
            
          
            
              <category>java14</category>
            
          
            
              <category>streams</category>
            
          
            
              <category>parallel</category>
            
          
            
              <category>bug</category>
            
          
        
        
          
            
              <category>Deep Dive</category>
            
          
            
              <category>Tricks &amp; Tips</category>
            
          
        
        
      </item>
      

    
  </channel>
</rss>