<?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>groovy on Solid Soft</title>
    <link>https://blog.solidsoft.pl/tags/groovy/</link>
    <description>Recent content in groovy on Solid Soft</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <copyright>©{year}, All Rights Reserved</copyright>
    <lastBuildDate>Tue, 05 Apr 2022 10:00:00 +0200</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>2</sy:updateFrequency>
    
        <atom:link href="https://blog.solidsoft.pl/tags/groovy/index.xml" rel="self" type="application/rss+xml" />
    
    
    

      
      <item>
        <title>More compact parameterized tests reporting in Spock 2.1</title>
        <link>https://blog.solidsoft.pl/2022/04/05/more-compact-parameterized-tests-reporting-in-spock-2.1/</link>
        <pubDate>Tue, 05 Apr 2022 10:00:00 +0200</pubDate>
        
        <atom:modified>Tue, 05 Apr 2022 10:00:00 +0200</atom:modified>
        <guid>https://blog.solidsoft.pl/2022/04/05/more-compact-parameterized-tests-reporting-in-spock-2.1/</guid>
        <description>Get even more compact reporting for parameterized tests with Spock 2.1.
  Historical background TL;TR. To just get a recipe, jump to the &amp;ldquo;More compact reporting&amp;rdquo; section. Parameterized tests, a place where Spock excels. A beautiful and powerful mechanism to reduce duplication across tests with a very readable table-like data representation (and powerful data providers if sophisticated custom logic is required).
When I started using Spock years ago (0.</description>
        <content:encoded>&lt;blockquote&gt;
&lt;p&gt;Get even more compact reporting for parameterized tests with Spock 2.1.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;figure &gt;
  
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2022/spock21-improved-unrolling.jpg&#34;  style=&#34;width:;height:;&#34;/&gt;
  
  
&lt;/figure&gt;

&lt;h2 id=&#34;historical-background&#34;&gt;Historical background&lt;/h2&gt;
&lt;div class=&#34;alert alert-info&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;strong&gt;TL;TR&lt;/strong&gt;. To just get a recipe, jump to the &lt;a href=&#34;#more-compact-reporting&#34;&gt;&amp;ldquo;More compact reporting&amp;rdquo; section&lt;/a&gt;.&lt;/div&gt;

&lt;p&gt;Parameterized tests, a place where Spock excels. A beautiful and powerful mechanism to reduce duplication across tests with a very readable table-like data representation (and powerful data providers if sophisticated custom logic is required).&lt;/p&gt;
&lt;p&gt;When I started using Spock years ago (0.6?), one question perpetually dinned in somebody&amp;rsquo;s ears. Why unrolling was not enabled by default? Adding &lt;code&gt;@Unroll&lt;/code&gt; (even at the test class level) was for me redundant, error prone and&amp;hellip; just boring. Due to that, I created a small &lt;a href=&#34;https://github.com/szpak/spock-global-unroll&#34; target=&#34;_blank&#34;&gt;spock-global-unroll&lt;/a&gt;
 extension which was dead simple. It was enough to just put it on a classpath (i.e. add as a dependency in Gradle or Maven) to have all the parameterized tests automatically unrolled in the whole project. Zero configuration, it just worked. You could remove all &lt;code&gt;@Unroll&lt;/code&gt; annotation (without parameters) in your project. I really liked it and used it in every project I had my fingers in. Have you ever heard about it?&lt;/p&gt;
&lt;p&gt;It was a rhetorical question. The vast majority of you did not. Why? Because it was an extension and people start looking for extensions when something does not work. For the extensions that improve (even dramatically) some aspect of your tests you would need to hear about them before (and I am hopeless at self promotion :-/).&lt;/p&gt;
&lt;p&gt;That was a reason why I &lt;a href=&#34;https://github.com/spockframework/spock/issues/967&#34; target=&#34;_blank&#34;&gt;pushed hard&lt;/a&gt;
 to have it available and enabled by default in the core of Spock 2.0. With a comprehensive implementation by &lt;a href=&#34;https://github.com/spockframework/spock/pull/1101&#34; target=&#34;_blank&#34;&gt;Björn Kautler&lt;/a&gt;
 in landed in 2.0-M3 to stay there for good. However, preparing some time ago my presentation &lt;a href=&#34;https://2022.geecon.org/speakers/info.html?id=647&#34; target=&#34;_blank&#34;&gt;&amp;ldquo;What you can expect from Spock 2?&amp;quot;&lt;/a&gt;
, I&amp;rsquo;ve noticed that it could be improved even more.&lt;/p&gt;
&lt;h2 id=&#34;default-verbose-reporting&#34;&gt;Default (verbose) reporting&lt;/h2&gt;
&lt;div class=&#34;alert alert-warning&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;strong&gt;Performance tip&lt;/strong&gt;. For Gradle projects, I prefer to execute unit and integration tests directly by IDEA, not by IDEA using Gradle (which - unfortunately - has been a default option since 2019 or so). First of all, it is much faster - a crucioal thing for TDD - and in the majority of cases it works perfectly fine. The examples below use that mode. You can read how to speed up your unit tests execution in my another blog post.&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s assume we have a 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;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-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;UnrollSpec&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;void&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should calculate number of characters in given animal name&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;animalName&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;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expectedLength&lt;/span&gt;
        &lt;span class=&#34;nl&#34;&gt;where:&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;animalName&lt;/span&gt;     &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;expectedLength&lt;/span&gt;
            &lt;span class=&#34;s2&#34;&gt;&amp;#34;dog&amp;#34;&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;s2&#34;&gt;&amp;#34;wolf&amp;#34;&lt;/span&gt;         &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;
            &lt;span class=&#34;s2&#34;&gt;&amp;#34;hippopotamus&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;12&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;Spock 2 unrolls parameterized tests by default displaying also all the used parameters. However, the output in IDEA is hard to read:&lt;/p&gt;


&lt;figure &gt;
  
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2022/spock21-long2-unroll.png&#34;  style=&#34;width:;height:;&#34;/&gt;
  
  
&lt;/figure&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;
To see the parameters it is usually needed to scroll the result window horizontally (if luckily your fancy mouse supports that :-) ) or reduce space available for the test standard output.&lt;/p&gt;


&lt;figure &gt;
  
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2022/spock21-long-unroll.png&#34;  style=&#34;width:;height:;&#34;/&gt;
  
  
&lt;/figure&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;
The crazy idea sprang in my mind - could the (repeated) feature name be omitted in the iterations name?&lt;/p&gt;
&lt;p&gt;To remove it for a particular test it is easy:&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-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;animaName: #animalName, expectedLength: #expectedLength&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//inconvenient - just for one test
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should calculate number of characters in given animal name&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;c1&#34;&gt;//...
&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;However, we have been just celebrating the removal of &lt;code&gt;@Unroll&lt;/code&gt;, not to be forced to put it back everywhere&amp;hellip; Luckily, Spock has a global configuration mechanism, could not it be used?&lt;/p&gt;
&lt;p&gt;After some minutes when I was analyzing the &lt;code&gt;UnrollExtension&lt;/code&gt; code, it turned out that no. &lt;code&gt;SpockConfig.groovy&lt;/code&gt; allows to define a custom &lt;code&gt;defaultPattern&lt;/code&gt;, but there is no way to display just the parameters. It is a FOSS project, what should be done in that case? :-)&lt;/p&gt;
&lt;h2 id=&#34;more-compact-reporting&#34;&gt;More compact reporting&lt;/h2&gt;
&lt;p&gt;The idea described in the previous section resulted in the improvements in Spock 2.1. There is a new configuration parameter which needs to be placed inside the &lt;code&gt;unroll {}&lt;/code&gt; closure in the &lt;code&gt;SpockConfig.groovy&lt;/code&gt; file (located for example in &lt;code&gt;src/test/resources&lt;/code&gt; - NOT together with the test classes):&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-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//in SpockConfig.groovy
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unroll&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;includeFeatureNameForIterations&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&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;figure &gt;
  
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2022/spock21-short2-unroll.png&#34;  style=&#34;width:;height:;&#34;/&gt;
  
  
&lt;/figure&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;
Much shorter, still meaningful output. And for all tests in the project!&lt;/p&gt;
&lt;p&gt;Note. If for some reason, you want to use it just for individual features &lt;code&gt;@Unroll(&#39;#dataVariablesWithIndex&#39;)&lt;/code&gt; can be used as well. Please refer the &lt;a href=&#34;https://spockframework.org/spock/docs/2.1/data_driven_testing.html#_configuration&#34; target=&#34;_blank&#34;&gt;official documentation&lt;/a&gt;
 for other use cases.&lt;/p&gt;
&lt;div class=&#34;alert alert-info&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;Keep in mind that &lt;code&gt;SpockConfig.groovy&lt;/code&gt; can &lt;a href=&#34;https://spockframework.org/spock/docs/2.1/extensions.html#spock-configuration-file&#34;&gt;be placed in various places&lt;/a&gt;, including your home directory - to more global impact.&lt;/div&gt;

&lt;h2 id=&#34;limitations&#34;&gt;Limitations&lt;/h2&gt;
&lt;p&gt;Why that marvelous feature was not enabled by default in Spock 2.1? We were thinking about that, but there two arguments against:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Backward compatibility.&lt;/li&gt;
&lt;li&gt;Poor support in some reporting tools.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;
The second point was more important. While the IDEA represents the test results with a very nice tree-like view, some other tools are not. The test report generated by Gradle or Maven&amp;rsquo;s Surefire displays them as a flat list, without the (parent) test name. As a result, not having the feature name in every iteration could be confusing.&lt;/p&gt;


&lt;figure &gt;
  
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2022/spock21-gradle-reporting2.png&#34;  style=&#34;width:;height:;&#34;/&gt;
  
  
&lt;/figure&gt;

&lt;p&gt;&lt;br /&gt;&lt;br /&gt;
As a result you might want to enable that feature conditionally only if executed in IDEA, 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;/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;c1&#34;&gt;//in SpockConfig.groovy
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;static&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;boolean&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;isExecutedFromIdea&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;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;System&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getProperty&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;java.class.path&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;contains&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;idea_rt.jar&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//any more reliable way?
&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;unroll&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;includeFeatureNameForIterations&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isExecutedFromIdea&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;That check is somehow fragile (e.g. doesn&amp;rsquo;t work if IDEA executes tests not directly, but using Gradle), but I wasn&amp;rsquo;t able to find anything better. Feel free to put your proposal in the comments.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;I hope that you also found &lt;code&gt;includeFeatureNameForIterations false&lt;/code&gt; useful. Hopefully, having better support in the reporting tools there will be no obstacles to make it enabled by default in Spock 3.0.&lt;/p&gt;
&lt;p&gt;Btw, in the middle of May, I will be talking about that and other new and noteworthy in Spock 2 at the &lt;a href=&#34;https://2022.geecon.org/speakers/info.html?id=647&#34; target=&#34;_blank&#34;&gt;GeeCON conference&lt;/a&gt;
. This time, finally, on-site, in Kraków, Poland (but the whole conference is in English).&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://2022.geecon.org/&#34; target=&#34;_blank&#34;&gt;

&lt;figure &gt;
  
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2022/spock21-geecon2022-big.png&#34; alt=&#34;GeeCON 2022 banner&#34; style=&#34;width:;height:;&#34;/&gt;
  
  
&lt;/figure&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;span style=&#34;opacity: 0.6&#34;&gt;Lead photo by &lt;a href=&#34;https://pixabay.com/users/paulina101-506132/&#34;&gt;Paulina101&lt;/a&gt;, published in &lt;a href=&#34;https://pixabay.com/photos/cd-cd-rom-spindle-reflection-517697/&#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/2022/spock21-improved-unrolling-thumbnail.jpg" medium="image"><media:title type="html">featured image</media:title></media:content>
        
        <media:content url="https://blog.solidsoft.pl/images/posts/2022/spock21-improved-unrolling-ratio.jpg" medium="image"><media:title type="html">meta image</media:title></media:content>
        
          
            
              <category>spock</category>
            
          
            
              <category>spock2</category>
            
          
            
              <category>spock-2.1</category>
            
          
            
              <category>testing</category>
            
          
            
              <category>groovy</category>
            
          
        
        
          
            
              <category>Tools</category>
            
          
        
        
      </item>
      
      <item>
        <title>Running Spock with unsupported Groovy version (Gradle &#43; Maven)</title>
        <link>https://blog.solidsoft.pl/2021/11/19/running-spock-with-unsupported-groovy-version-gradle-maven/</link>
        <pubDate>Fri, 19 Nov 2021 00:10:00 +0200</pubDate>
        
        <atom:modified>Wed, 02 Feb 2022 23:50:00 +0100</atom:modified>
        <guid>https://blog.solidsoft.pl/2021/11/19/running-spock-with-unsupported-groovy-version-gradle-maven/</guid>
        <description>Stuck with the &amp;lsquo;The Spock compiler plugin cannot execute because Spock 1.3-groovy-2.5 (3.0) is not compatible with Groovy 3.0 (4.0)&amp;rsquo; error message? Find out what can be done about that (using Gradle and Maven).
  Historical background In the dim and distance past, when Groovy 1.x occasionally had some unpleasant (also runtime) backward compatibility issues, Spock had started to be built for the particular Groovy version individually. There were spock-0.</description>
        <content:encoded>&lt;blockquote&gt;
&lt;p&gt;Stuck with the &amp;lsquo;The Spock compiler plugin cannot execute because Spock 1.3-groovy-2.5 (3.0) is not compatible with Groovy 3.0 (4.0)&amp;rsquo; error message? Find out what can be done about that (using Gradle and Maven).&lt;/p&gt;
&lt;/blockquote&gt;


&lt;figure &gt;
  
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2021/spock2-groovy4.jpg&#34;  style=&#34;width:;height:;&#34;/&gt;
  
  
&lt;/figure&gt;

&lt;h2 id=&#34;historical-background&#34;&gt;Historical background&lt;/h2&gt;
&lt;p&gt;In the dim and distance past, when Groovy 1.x occasionally had some unpleasant (also runtime) backward compatibility issues, Spock had started to be built for the particular Groovy version individually. There were &lt;code&gt;spock-0.5-groovy-1.6&lt;/code&gt;, &lt;code&gt;spock-0.5-groovy-1.7&lt;/code&gt; and &lt;code&gt;spock-0.5-groovy-1.8&lt;/code&gt; for instance. To help people choose the right Spock and the Groovy versions, the runtime check was added to fail the compilation (at the AST transformation level) with the meaningful error message, in the situation Spock was compiled with the different Groovy version that is available at runtime, e.g.:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The Spock compiler plugin refused to run because Spock 1.3-groovy-2.5 is not compatible with Groovy 3.0.4. For more information,
see http://versioncheck.spockframework.org Spock location: .../spock-1.3-groovy-2.5.jar, Groovy location: .../groovy-3.0.4.jar
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The error message is very clear. The reasoning behind this decision is good, and definitely it can help developers to detect problems with the dependencies. However, it can also greatly complicate development, especially taking into account rather rarely released new Spock versions.&lt;/p&gt;
&lt;p&gt;If you are here, because of that error visible in your build, jump to the proper section to see what can be done about the problem.&lt;/p&gt;
&lt;h2 id=&#34;possible-options&#34;&gt;Possible options&lt;/h2&gt;
&lt;h3 id=&#34;spock-13-and-groovy-30&#34;&gt;Spock 1.3 and Groovy 3.0&lt;/h3&gt;
&lt;p&gt;Unfortunately, you are out of luck. If you stuck with Spock 1.3 (e.g. migration to Spock 2.0 is blocked for some reasons) there are two (mediocre) options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Switch to &lt;code&gt;Spock 1.3-SNAPSHOT&lt;/code&gt;. The version compatibility check is relaxed in the SNAPSHOT builds of Spock 1.3. What&amp;rsquo;s more, there were multiple reports that (in the majority of cases - some corner cases remains) Spock &lt;code&gt;1.3-groovy-2.5-SNAPSHOT&lt;/code&gt; works fine with Groovy &lt;code&gt;3.0.x&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;There are no plans to release any new maintenance release of Spock 1.x. However, you can still &lt;a href=&#34;https://github.com/spockframework/spock/issues&#34; target=&#34;_blank&#34;&gt;create a new issue on GitHub&lt;/a&gt;
 and try to convince The Spock Developers to make 1.3.1 with that change :-).&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;spock-20-and-groovy-30&#34;&gt;Spock 2.0+ and Groovy 3.0&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;The Spock compiler plugin refused to run because Spock 2.0-groovy-2.5 is not compatible with Groovy 3.0.9.
For more information (including enforce mode), see http://docs.spockframework.org (section &#39;Known Issues&#39;). 
Spock location: .../spock-2.0-groovy-2.5.jar
Groovy location: .../groovy-3.0.9.jar
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That a trivial case. Just change Spock version from 2.0-groovy-2.5 to 2.0-groovy-3.0, and you are set.&lt;/p&gt;
&lt;h3 id=&#34;spock-2021-and-groovy-40&#34;&gt;Spock 2.0/2.1 and Groovy 4.0&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;The Spock compiler plugin refused to run because Spock 2.0-groovy-3.0 is not compatible with Groovy 4.0.0-beta-2.
For more information (including enforce mode), see http://docs.spockframework.org (section &#39;Known Issues&#39;). 
Spock location: .../spock-2.0-groovy-3.0.jar
Groovy location: .../groovy-4.0.0-beta-2.jar
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This variant assumes that you use Groovy 4 (SNAPSHOT, beta or a regular version) and Spock 2.0-groovy-3.0 (or 2.1). The error message is even more precise than in Spock 1.3, suggesting the &lt;a href=&#34;http://spockframework.org/spock/docs/2.0-M3/known_issues.html#_groovy_version_compatibility&#34; target=&#34;_blank&#34;&gt;&amp;lsquo;Known Issues&amp;rsquo;&lt;/a&gt;
 section in the Spock documentation. We can leverage a brand-new system property &lt;code&gt;spock.iKnowWhatImDoing.disableGroovyVersionCheck&lt;/code&gt;, introduced right in Spock 2.0-M3, which allows to disable the version check - of course, at your own risk :-).&lt;/p&gt;
&lt;p&gt;Btw, if you in a hurry (e.g. just to test something), it is also possible just to switch Spock to SNAPSHOT version which accepts (almost) any Groovy version.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Btw2, if you prefer to just jump into code, there is a &lt;a href=&#34;https://github.com/szpak/code-examples-and-poc/tree/master/spock2-groovy4-gradle-maven&#34; target=&#34;_blank&#34;&gt;code repository&lt;/a&gt;
 with working examples for Gradle and Maven.&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id=&#34;gradle&#34;&gt;Gradle&lt;/h4&gt;
&lt;div class=&#34;alert alert-warning&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;As Groovy 4 changed its &lt;code&gt;groupId&lt;/code&gt; from &lt;code&gt;org.codehaus.groovy&lt;/code&gt; to &lt;code&gt;org.apache.groovy&lt;/code&gt; it is required to &lt;strong&gt;add implicit exclusion for spock-2.0-groovy-3.0 transitive dependencies&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;testImplementation(&amp;quot;org.spockframework:spock-core:2.0-groovy-3.0&amp;quot;) {
    exclude group: &#39;org.codehaus.groovy&#39;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;to avoid conflicting Groovy versions on a classpath (it&amp;rsquo;s nice that Gradle is able to detect that!):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; Task :compileTestGroovy FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task &#39;:compileTestGroovy&#39;.
&amp;gt; Could not resolve all files for configuration &#39;:testCompileClasspath&#39;.
   &amp;gt; Could not resolve org.apache.groovy:groovy:4.0.0-beta-2.
     Required by:
         project :
         project : &amp;gt; org.apache.groovy:groovy:4.0.0-beta-2 &amp;gt; org.apache.groovy:groovy-bom:4.0.0-beta-2
      &amp;gt; Module &#39;org.apache.groovy:groovy&#39; has been rejected:
           Cannot select module with conflict on capability &#39;org.codehaus.groovy:groovy:4.0.0-beta-2&#39; also provided by [org.codehaus.groovy:groovy:3.0.8(compile)]
   &amp;gt; Could not resolve org.codehaus.groovy:groovy:3.0.8.
     Required by:
         project : &amp;gt; org.spockframework:spock-core:2.0-groovy-3.0
      &amp;gt; Module &#39;org.codehaus.groovy:groovy&#39; has been rejected:
           Cannot select module with conflict on capability &#39;org.codehaus.groovy:groovy:3.0.8&#39; also provided by [org.apache.groovy:groovy:4.0.0-beta-2(groovyApiElements)]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It won&amp;rsquo;t be required for Spock 2.0-groovy-4.0, once available.&lt;/p&gt;
&lt;/div&gt;

&lt;div class=&#34;alert alert-info&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;&lt;strong&gt;To be able use Groovy 4, Gradle 6.7+ is &lt;a href=&#34;https://github.com/gradle/gradle/issues/13657&#34;&gt;required&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With earlier Gradle version you might got some misleading errors about not resolvable dependency to &lt;code&gt;org.codehaus.groovy:groovy:4.0.0-beta-2&lt;/code&gt;, even though you configured &lt;code&gt;org.apache.groovy:groovy:4.0.0-beta-2&lt;/code&gt; with the correct, changed group id.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Execution failed for task &#39;:compileTestGroovy&#39;.
&amp;gt; Could not resolve all files for configuration &#39;:detachedConfiguration1&#39;.
   &amp;gt; Could not find org.codehaus.groovy:groovy:4.0.0-beta-2.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The obvious way to add system properties to the Gradle execution itself is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./gradlew check -Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true     //wrong way
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unfortunately it doesn&amp;rsquo;t work:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; Task :compileTestGroovy FAILED
startup failed:
Could not instantiate global transform class org.spockframework.compiler.SpockTransform specified at jar:file:/home/foobar/.m2/repository/org/spockframework/spock-core/2.0-groovy-3.0/spock-core-2.0-groovy-3.0.jar!/META-INF/services/org.codehaus.groovy.transform.ASTTransformation  because of exception org.spockframework.util.IncompatibleGroovyVersionException: The Spock compiler plugin cannot execute because Spock 2.0-groovy-3.0 is not compatible with Groovy 4.0.0-beta-2. For more information (including enforce mode), see http://docs.spockframework.org (section &#39;Known Issues&#39;).
Spock artifact: file:/home/foobar/.m2/repository/org/spockframework/spock-core/2.0-groovy-3.0/.../spock-core-2.0-groovy-3.0.jar
Groovy artifact: file:/home/foobar/.gradle/caches/modules-2/files-2.1/org.apache.groovy/groovy/4.0.0-beta-2/.../groovy-4.0.0-beta-2.jar

1 error


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task &#39;:compileTestGroovy&#39;.
&amp;gt; Compilation failed; see the compiler error output for details.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;After some searching on the Internet, we can find out that tests in Gradle are (by default) executed in a separate JVM, to it is required to pass the aforementioned system property to the &lt;code&gt;test&lt;/code&gt; task:&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;/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;test&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;systemProperty&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;spock.iKnowWhatImDoing.disableGroovyVersionCheck&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;//doesn&amp;#39;t work
&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;However, it still fails:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; Task :compileTestGroovy FAILED
startup failed:
Could not instantiate global transform class org.spockframework.compiler.SpockTransform specified at ...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Hmm, maybe it would be better to refer the Gradle test task by type?&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;/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;tasks&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;withType&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Test&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;configureEach&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;systemProperty&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;spock.iKnowWhatImDoing.disableGroovyVersionCheck&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;//doesn&amp;#39;t work either
&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;It fails with the same error message :-/. What is wrong?&lt;/p&gt;
&lt;p&gt;The key difference - quite easy to miss - is the fact the exception is thrown not during the test execution, but during the compilation phrase. Then, the main Spock AST transformation checks if it could be applied:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; Task :compileTestGroovy FAILED   &amp;lt;--------- :compileTestGroovy not :test !
startup failed:
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It is definitely less popular case, and I had a problem to find any sensible source of wisdom proposing a complete solution. One of the possible option (which I talk about deeper in the article about &lt;a href=&#34;https://blog.solidsoft.pl/2020/03/02/enable-java-14-preview-features-in-gradle-maven-and-idea/&#34;&gt;enabling preview features&lt;/a&gt;
 of the new Java versions) is &lt;code&gt;CompileOptions&lt;/code&gt; (e.g. &lt;code&gt;options.compilerArgs.add(&#39;--enable-preview&#39;)&lt;/code&gt; in the &lt;a href=&#34;https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/compile/GroovyCompile.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;GroovyCompile&lt;/code&gt;&lt;/a&gt;
 task. The second might be &lt;code&gt;GroovyCompileOptions&lt;/code&gt; also in &lt;code&gt;GroovyCompile&lt;/code&gt;. However, it does not bring expected result. After some digging, I was able to find out, that as the Groovy compilation is performed in the forked JVM and the right way to achieve the goal is:&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;/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;tasks&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;withType&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;GroovyCompile&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;configureEach&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;options&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;forkOptions&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;jvmArgs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true&amp;#39;&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//it works! But be aware that &amp;#34;options&amp;#34; not &amp;#34;groovyOptions&amp;#34;!
&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;And it works as expected:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; Task :compileTestGroovy
Executing Spock 2.0-groovy-3.0 with NOT compatible Groovy version 4.0.0-beta-2 due to set spock.iKnowWhatImDoing.disableGroovyVersionCheck system property set. This is unsupported and may result in weird runtime errors!

&amp;gt; Task :test
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;displaying a nice disclaimer :). Spock 2.0-groovy-3.0 is used together with Groovy 4.&lt;/p&gt;
&lt;p&gt;Btw, if you see just not very helpful error message:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Could not instantiate global transform class org.spockframework.compiler.SpockTransform specified at
jar:file:/.../spock-core-.../org.codehaus.groovy.transform.ASTTransformation
because of exception java.lang.reflect.InvocationTargetException
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;it is caused by &lt;a href=&#34;https://issues.apache.org/jira/browse/GROOVY-9469&#34; target=&#34;_blank&#34;&gt;GROOVY-9469&lt;/a&gt;
 which affects Groovy 3 and was fixed in 3.0.3. Upgrade Groovy to see more verbose error message.&lt;/p&gt;
&lt;h4 id=&#34;maven&#34;&gt;Maven&lt;/h4&gt;
&lt;div class=&#34;alert alert-warning&#34; role=&#34;alert&#34; data-dir=&#34;ltr&#34;&gt;&lt;p&gt;As Groovy 4 changed its &lt;code&gt;groupId&lt;/code&gt; from &lt;code&gt;org.codehaus.groovy&lt;/code&gt; to &lt;code&gt;org.apache.groovy&lt;/code&gt; it is required to &lt;strong&gt;add implicit exclusion for spock-2.0-groovy-3.0 transitive dependencies&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;dependencies&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.spockframework&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;spock-core&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;${spock.version}&amp;lt;/version&amp;gt;
        &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;exclusions&amp;gt;
            &amp;lt;!-- to do not have conflicting Groovy versions - Groovy 4 changed groupId from &amp;quot;org.codehaus.groovy&amp;quot; to &amp;quot;org.apache.groovy&amp;quot; --&amp;gt;
            &amp;lt;exclusion&amp;gt;
                &amp;lt;groupId&amp;gt;org.codehaus.groovy&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;*&amp;lt;/artifactId&amp;gt;
            &amp;lt;/exclusion&amp;gt;
        &amp;lt;/exclusions&amp;gt;
    &amp;lt;/dependency&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.groovy&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;groovy&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;4.0.0-beta-2&amp;lt;/version&amp;gt;
    &amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;to have your tests executed with Groovy 4 instead of (silently) with Groovy 3, taken from a transitive dependency of Spock 2.0-groovy-3.0!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[INFO] --- gmavenplus-plugin:1.13.0:compileTests (default) @ spock2-groovy4-maven ---
[INFO] Using isolated classloader, without GMavenPlus classpath.
[INFO] Using Groovy 3.0.8 to perform compileTests.     &amp;lt;---- Without exclusion, it is executed &amp;quot;silently&amp;quot; with old Groovy! 
[INFO] Parallel parsing disabled.
[INFO] Compiled 1 file.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It won&amp;rsquo;t be required for Spock 2.0-groovy-4.0, once available.&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;Writing my Spock, Groovy and modern Java related tutorials, I try to cover also the Maven users, which still is quite popular build tool :-). Usually, it takes much more (XML) lines to achieve the same in Maven in comparison to Gradle, however, sometimes it just works flawlessly without any additional effort. Unfortunately, it was not the case this time.&lt;/p&gt;
&lt;p&gt;The build with Spock-2.0-groovy-3.0 and Groovy 4.0.0 by default fails with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[ERROR] Failed to execute goal org.codehaus.gmavenplus:gmavenplus-plugin:1.8.1:compileTests (default) on project spock2-migration-maven: Error occurred while calling a method on a Groovy class from classpath. InvocationTargetException: startup failed:
[ERROR] Could not instantiate global transform class org.spockframework.compiler.SpockTransform specified at jar:file:/home/foobar/.m2/repository/org/spockframework/spock-core/2.0-groovy-3.0/spock-core-2.0-groovy-3.0.jar!/META-INF/services/org.codehaus.groovy.transform.ASTTransformation  because of exception org.spockframework.util.IncompatibleGroovyVersionException: The Spock compiler plugin cannot execute because Spock 2.0-groovy-3.0 is not compatible with Groovy 4.0.0-beta-2. For more information (including enforce mode), see http://docs.spockframework.org (section &#39;Known Issues&#39;).
[ERROR] Spock artifact: file:/home/foobar/.m2/repository/org/spockframework/spock-core/2.0-groovy-3.0/spock-core-2.0-groovy-3.0.jar
[ERROR] Groovy artifact: file:/home/foobar/.m2/repository/org/apache/groovy/groovy/4.0.0-beta-2/groovy-4.0.0-beta-2.jar
[ERROR] 
[ERROR] 1 error
[ERROR] -&amp;gt; [Help 1]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To make the long story short, I started with the plain Maven properties:&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;/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-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;project&amp;gt;&lt;/span&gt;
...
  &lt;span class=&#34;nt&#34;&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
     &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- doesn&amp;#39;t work --&amp;gt;&lt;/span&gt;
     &lt;span class=&#34;nt&#34;&gt;&amp;lt;spock.iKnowWhatImDoing.disableGroovyVersionCheck&amp;gt;&lt;/span&gt;true&lt;span class=&#34;nt&#34;&gt;&amp;lt;/spock.iKnowWhatImDoing.disableGroovyVersionCheck&amp;gt;&lt;/span&gt;
  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;
...
&lt;span class=&#34;nt&#34;&gt;&amp;lt;/project&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 fails. Next, I added the following to the compiler parameters:&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;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;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&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-xml&#34; data-lang=&#34;xml&#34;&gt;    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;lt;build&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;plugins&amp;gt;&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.apache.maven.plugins&lt;span class=&#34;nt&#34;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;maven-compiler-plugin&lt;span class=&#34;nt&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;3.8.1&lt;span class=&#34;nt&#34;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- doesn&amp;#39;t work --&amp;gt;&lt;/span&gt;
                    &lt;span class=&#34;nt&#34;&gt;&amp;lt;compilerArgs&amp;gt;&lt;/span&gt;
                        &lt;span class=&#34;nt&#34;&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;-v&lt;span class=&#34;nt&#34;&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                        &lt;span class=&#34;nt&#34;&gt;&amp;lt;arg&amp;gt;&lt;/span&gt;-Dspock.iKnowWhatImDoing.disableGroovyVersionCheck=true&lt;span class=&#34;nt&#34;&gt;&amp;lt;/arg&amp;gt;&lt;/span&gt;
                    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/compilerArgs&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
            &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- ... --&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/build&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- ... --&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;however, it doesn&amp;rsquo;t affect Groovy compilation itself. I even took a look at the &lt;code&gt;gmavenplus&lt;/code&gt; plugin parameters and Groovy&amp;rsquo;s &lt;a href=&#34;https://docs.groovy-lang.org/latest/html/api/org/codehaus/groovy/control/CompilerConfiguration.html&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;CompilerConfiguration&lt;/code&gt;&lt;/a&gt;
, but without any effect. In the end, I was able to achieve that with another plugin &lt;code&gt;properties-maven&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;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;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;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&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-xml&#34; data-lang=&#34;xml&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.codehaus.mojo&lt;span class=&#34;nt&#34;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;properties-maven-plugin&lt;span class=&#34;nt&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.0.0&lt;span class=&#34;nt&#34;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
                    &lt;span class=&#34;nt&#34;&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;set-system-properties&lt;span class=&#34;nt&#34;&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                    &lt;span class=&#34;nt&#34;&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;
                        &lt;span class=&#34;c&#34;&gt;&amp;lt;!-- works fine --&amp;gt;&lt;/span&gt;
                        &lt;span class=&#34;nt&#34;&gt;&amp;lt;property&amp;gt;&lt;/span&gt;
                            &lt;span class=&#34;nt&#34;&gt;&amp;lt;name&amp;gt;&lt;/span&gt;spock.iKnowWhatImDoing.disableGroovyVersionCheck&lt;span class=&#34;nt&#34;&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
                            &lt;span class=&#34;nt&#34;&gt;&amp;lt;value&amp;gt;&lt;/span&gt;true&lt;span class=&#34;nt&#34;&gt;&amp;lt;/value&amp;gt;&lt;/span&gt;
                        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/property&amp;gt;&lt;/span&gt;
                    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/plugin&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;resulting in:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[INFO] --- gmavenplus-plugin:1.8.1:compileTests (default) @ spock2-migration-maven ---
[INFO] Using isolated classloader, without GMavenPlus classpath.
[INFO] Using Groovy 4.0.0-beta-2 to perform compileTests.
Executing Spock 2.0-groovy-3.0 with NOT compatible Groovy version 4.0.0-beta-2 due to set spock.iKnowWhatImDoing.disableGroovyVersionCheck system property set. This is unsupported and may result in weird runtime errors!
[INFO] Compiled 10 files.
[INFO] 
[INFO] --- maven-surefire-plugin:3.0.0-M4:test (default-test) @ spock2-migration-maven ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;It turned out to be quite easy (if you know what to use :-) ), but - unless I missed something - it is somehow not much covered in the existing tutorials or documentation.&lt;/p&gt;
&lt;h3 id=&#34;potential-issue-in-intellij-idea&#34;&gt;Potential issue in IntelliJ IDEA&lt;/h3&gt;
&lt;p&gt;Even though, having your up-and-running Maven project configured as above, you might still encounter the incompatibility error after importing it in Idea:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Groovyc: While compiling [tests of spock2-groovy4-gradle.test]: Could not instantiate global transform class org.spockframework.compiler.SpockTransform specified at jar:file:/home/&amp;hellip;/spock-core-2.0-groovy-3.0.jar!/META-INF/services/org.codehaus.groovy.transform.ASTTransformation because of exception java.lang.NullPointerException: Cannot invoke &amp;ldquo;java.net.URL.toString()&amp;rdquo; because the return value of &amp;ldquo;java.security.CodeSource.getLocation()&amp;rdquo; is null&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;del&gt;The problem is caused by a limitation of Idea (&lt;a href=&#34;https://youtrack.jetbrains.com/issue/IDEA-287642&#34; target=&#34;_blank&#34;&gt;IDEA-287642&lt;/a&gt;
), which does not allow providing custom system properties for groovyc compilation (just for javac). You might want to vote for that issue.&lt;/del&gt; In fact, as &lt;a href=&#34;https://youtrack.jetbrains.com/issue/IDEA-287642#focus=Comments-27-5733123.0-0&#34; target=&#34;_blank&#34;&gt;Paul King&lt;/a&gt;
 pointed out, there is a way to set that property for all the compilers used in the project with &lt;code&gt;Settings → Compiler → Shared build process VM options&lt;/code&gt;. In the context of Spock, it should be enough.&lt;/p&gt;
&lt;p&gt;The error itself is not very meaningful (&lt;code&gt;NullPointerException&lt;/code&gt;) which in turn is caused by an unexpected behavior of Idea, reported as &lt;a href=&#34;https://youtrack.jetbrains.com/issue/IDEA-287643&#34; target=&#34;_blank&#34;&gt;IDEA-287643&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;It is worth to mention, the same problem might occur also with Gradle, once &amp;ldquo;Build and run&amp;rdquo; is manually set to &amp;ldquo;Idea&amp;rdquo; (instead of &amp;ldquo;Gradle&amp;rdquo; - default behavior, but not the fastest one).&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;The main reason, I implemented that feature in Spock was development of Groovy 4. I didn&amp;rsquo;t feel comfortable seeing The Groovy Team to be forced to use the Spock snapshot version in the master (Groovy 4.x) builds. With Spock-2.0-M3 it was &lt;a href=&#34;https://github.com/apache/groovy/pull/1281&#34; target=&#34;_blank&#34;&gt;simplified&lt;/a&gt;
. The same construction can be used in your project while playing with Groovy 4 (in beta as of XI 2021), in the way I precised for Gradle and Maven (which in turn can be really confusing on their own way which motivated me to write this short post :-) ). There is &lt;a href=&#34;https://github.com/spockframework/spock/issues/1374#issuecomment-932374972&#34; target=&#34;_blank&#34;&gt;a plan&lt;/a&gt;
 to add the official support for Groovy 4 in Spock, once it is closer to Groovy 4.0.0-final.&lt;/p&gt;
&lt;p&gt;Btw, there is a &lt;a href=&#34;https://github.com/szpak/code-examples-and-poc/tree/master/spock2-groovy4-gradle-maven&#34; target=&#34;_blank&#34;&gt;code repository&lt;/a&gt;
 with working examples for Gradle and Maven.&lt;/p&gt;
&lt;p&gt;P.S. If you bumped into that topic during Spock 1.3 -&amp;gt; 2.0 migration, there is a dedicated &lt;a href=&#34;https://blog.solidsoft.pl/2020/01/02/migrating-spock-1.3-tests-to-spock-2.0/&#34;&gt;migration guide article&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Updated 2021-01-31&lt;/strong&gt;. Added section about potential issue with IntelliJ IDEA.&lt;br /&gt;
&lt;strong&gt;Updated 2021-02-02&lt;/strong&gt;. Add workaround suggested by &lt;a href=&#34;https://twitter.com/paulk_asert&#34; target=&#34;_blank&#34;&gt;Paul King&lt;/a&gt;
 about the potential issue with IntelliJ IDEA.&lt;/p&gt;
&lt;span style=&#34;opacity: 0.6&#34;&gt;Lead photo by &lt;a href=&#34;https://pixabay.com/users/geralt-9301/&#34;&gt;geralt&lt;/a&gt;, published in &lt;a href=&#34;https://pixabay.com/illustrations/place-name-sign-plan-success-749613/&#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/2021/spock2-groovy4-thumbnail.jpg" medium="image"><media:title type="html">featured image</media:title></media:content>
        
        <media:content url="https://blog.solidsoft.pl/images/posts/2021/spock2-groovy4-ratio.jpg" medium="image"><media:title type="html">meta image</media:title></media:content>
        
          
            
              <category>spock</category>
            
          
            
              <category>spock2</category>
            
          
            
              <category>spock-2.0</category>
            
          
            
              <category>testing</category>
            
          
            
              <category>groovy</category>
            
          
            
              <category>groovy4</category>
            
          
            
              <category>gradle</category>
            
          
            
              <category>maven</category>
            
          
        
        
          
            
              <category>Tools</category>
            
          
        
        
      </item>
      
      <item>
        <title>What happened to Groovy dependencies in Spock 2.0?</title>
        <link>https://blog.solidsoft.pl/2020/06/16/what-happened-to-groovy-dependencies-in-spock-2.0/</link>
        <pubDate>Tue, 16 Jun 2020 10:00:00 +0200</pubDate>
        
        <atom:modified>Tue, 16 Jun 2020 10:00:00 +0200</atom:modified>
        <guid>https://blog.solidsoft.pl/2020/06/16/what-happened-to-groovy-dependencies-in-spock-2.0/</guid>
        <description>Spock 2.0(-M3) reduced number of provided Groovy dependencies. If you started to get various Groovy-related ClassNotFoundExceptions after migration and wonder why and what to do, read on.
  Historical background Originally Groovy was just one jar to rule them all. However, in process of time, that jar became bigger and bigger. Groovy 2 was the first version promoting the usage of (several at that time) Groovy modules, as a supplemental to groovy.</description>
        <content:encoded>&lt;blockquote&gt;
&lt;p&gt;Spock 2.0(-M3) reduced number of provided Groovy dependencies. If you started to get various Groovy-related &lt;code&gt;ClassNotFoundException&lt;/code&gt;s after migration and wonder why and what to do, read on.&lt;/p&gt;
&lt;/blockquote&gt;


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

&lt;h2 id=&#34;historical-background&#34;&gt;Historical background&lt;/h2&gt;
&lt;p&gt;Originally Groovy was just one &lt;code&gt;jar&lt;/code&gt; to rule them all. However, in process of time, that jar became bigger and bigger. Groovy 2 was the first version promoting the usage of (several at that time) Groovy modules, as a supplemental to &lt;code&gt;groovy.jar&lt;/code&gt;. However the adoption of that approach was slowly and &lt;code&gt;groovy-all&lt;/code&gt; remained prevalent in &lt;code&gt;pom.xml&lt;/code&gt; and &lt;code&gt;build.gradle&lt;/code&gt; files.&lt;/p&gt;
&lt;p&gt;What even worse, having some projects use &lt;code&gt;groovy.jar&lt;/code&gt; plus some modules (e.g. &lt;code&gt;groovy-json.jar&lt;/code&gt; or &lt;code&gt;groovy-xml.jar&lt;/code&gt;) while some other preferring good old &lt;code&gt;groovy-all.jar&lt;/code&gt; could lead to version clashes as for Maven or Gradle those were independent packages. To avoid that it was quite common to see the defensive Groovy exclusions:&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;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;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-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;dependencies&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.codehaus.gmaven.runtime&lt;span class=&#34;nt&#34;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;YYY&lt;span class=&#34;nt&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.2&lt;span class=&#34;nt&#34;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;exclusions&amp;gt;&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;lt;exclusion&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.codehaus.groovy&lt;span class=&#34;nt&#34;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
                &lt;span class=&#34;nt&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;*&lt;span class=&#34;nt&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
            &lt;span class=&#34;nt&#34;&gt;&amp;lt;/exclusion&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;/exclusions&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.codehaus.groovy&lt;span class=&#34;nt&#34;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;groovy-all&lt;span class=&#34;nt&#34;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
        &lt;span class=&#34;nt&#34;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${groovy.version}&lt;span class=&#34;nt&#34;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&#34;nt&#34;&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;span class=&#34;nt&#34;&gt;&amp;lt;/dependencies&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;and declare all required Groovy dependencies on their own.&lt;/p&gt;
&lt;p&gt;Groovy 2.5 switched to the model of Maven&amp;rsquo;s BOM (Bill Of Materials) where &lt;code&gt;groovy-all&lt;/code&gt; isn&amp;rsquo;t a binary jar itself, but rather has the official Groovy modules as dependencies. Thanks to that, Maven and Gradle have easier to keep the versioning of the particular modules consistent. This holds for Groovy 3 which still provides the &lt;code&gt;groovy-all&lt;/code&gt; BOM.&lt;/p&gt;
&lt;h2 id=&#34;groovy-dependencies-in-spock-13&#34;&gt;Groovy dependencies in Spock 1.3&lt;/h2&gt;
&lt;p&gt;Spock 1.2 switched from &lt;code&gt;groovy-all.jar&lt;/code&gt; to &lt;code&gt;groovy.jar&lt;/code&gt; + modules. Unfortunately due to historical reasons it was a lot of modules:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;testRuntimeClasspath - Runtime classpath of source set &#39;test&#39;.
+--- org.spockframework:spock-core:2.0-M2-groovy-3.0
|    +--- org.codehaus.groovy:groovy:3.0.0
|    +--- org.codehaus.groovy:groovy-json:3.0.0
|    |    \--- org.codehaus.groovy:groovy:3.0.0
|    +--- org.codehaus.groovy:groovy-nio:3.0.0
|    |    \--- org.codehaus.groovy:groovy:3.0.0
|    +--- org.codehaus.groovy:groovy-macro:3.0.0
|    |    \--- org.codehaus.groovy:groovy:3.0.0
|    +--- org.codehaus.groovy:groovy-templates:3.0.0
|    |    +--- org.codehaus.groovy:groovy-xml:3.0.0
|    |    |    \--- org.codehaus.groovy:groovy:3.0.0
|    |    \--- org.codehaus.groovy:groovy:3.0.0
|    +--- org.codehaus.groovy:groovy-test:3.0.0
|    |    \--- org.codehaus.groovy:groovy:3.0.0
|    +--- org.codehaus.groovy:groovy-sql:3.0.0
|    |    \--- org.codehaus.groovy:groovy:3.0.0
|    +--- org.codehaus.groovy:groovy-xml:3.0.0 (*)
|    \--- org.junit.platform:junit-platform-engine:1.5.2
|         ...
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As a result the following was quite common:&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;/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;test&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;org.spockframework:spock-core:1.3-groovy-2.5&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 class=&#34;n&#34;&gt;exclude&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;group:&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;org.codehaus.groovy&amp;#39;&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//get rid of all dependant groovy modules
&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;test&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;org.codehaus.groovy:groovy:2.5.11&amp;#39;&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//apply only those needed
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;test&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;org.codehaus.groovy:groovy-json:2.5.11&amp;#39;&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;test&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;org.codehaus.groovy:groovy-templates:2.5.11&amp;#39;&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;However, it turned out that in fact all those extra modules are not needed internally for &lt;code&gt;spock-core&lt;/code&gt; and they were rather provided as a convenience for end users.&lt;/p&gt;
&lt;h2 id=&#34;groovy-dependencies-in-spock-20&#34;&gt;Groovy dependencies in Spock 2.0+&lt;/h2&gt;
&lt;p&gt;Starting with Spock 2.0-M3 the Groovy dependencies were &lt;a href=&#34;https://github.com/spockframework/spock/pull/1109&#34; target=&#34;_blank&#34;&gt;simplified&lt;/a&gt;
 to just &lt;code&gt;groovy.jar&lt;/code&gt;. Thanks to that you safe some bandwidth on the initial build (what is well-timed ;-) ) and the CI builds without proper caching take slightly shorter.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;testCompileClasspath - Compile classpath for source set &#39;test&#39;.
+--- org.spockframework:spock-core:2.0-M3-groovy-3.0
|    +--- org.codehaus.groovy:groovy:3.0.4
|    +--- org.junit.platform:junit-platform-engine:1.7.1-M1
|         ...
...
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;As a downside, after the migration to Spock-2.0-M3+, in rare cases you might get &lt;code&gt;ClassNotFoundException: groovy.sql.Sql&lt;/code&gt;, &lt;code&gt;ClassNotFoundException: groovy.json.JsonSlurper&lt;/code&gt; or &lt;code&gt;ClassNotFoundException: groovy.util.XmlParser&lt;/code&gt;. That error suggest that you use those classes somewhere in your tests, but the corresponding dependency is not declared implicitly in your build configuration (and it&amp;rsquo;s not accidentally provided by &lt;code&gt;spock-core&lt;/code&gt; any longer). The quick fix is to add &lt;code&gt;org.codehaus.groovy:groovy-sql:3.0.X&lt;/code&gt;, &lt;code&gt;org.codehaus.groovy:groovy-json:3.0.X&lt;/code&gt; or similar explicitly.&lt;/p&gt;
&lt;p&gt;P.S. If you bumped into that topic during Spock 1.3 -&amp;gt; 2.0 migration, there is a dedicated &lt;a href=&#34;https://blog.solidsoft.pl/2020/01/02/migrating-spock-1.3-tests-to-spock-2.0/&#34;&gt;migration guide article&lt;/a&gt;
.&lt;/p&gt;
&lt;span style=&#34;opacity: 0.6&#34;&gt;Lead photo by &lt;a href=&#34;https://pixabay.com/users/tumisu-148124/&#34;&gt;Tumisu&lt;/a&gt;, published in &lt;a href=&#34;https://pixabay.com/photos/magnifying-glass-detective-looking-4340698/&#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/spock-groovy-dependencies-thumbnail.jpg" medium="image"><media:title type="html">featured image</media:title></media:content>
        
        <media:content url="https://blog.solidsoft.pl/images/posts/2020/spock-groovy-dependencies-ratio.jpg" medium="image"><media:title type="html">meta image</media:title></media:content>
        
          
            
              <category>spock</category>
            
          
            
              <category>spock2</category>
            
          
            
              <category>spock-2.0</category>
            
          
            
              <category>testing</category>
            
          
            
              <category>groovy</category>
            
          
        
        
          
            
              <category>Tools</category>
            
          
        
        
      </item>
      
      <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>Places where you REALLY NEED to use &#39;assert&#39; keyword in Spock assertions</title>
        <link>https://blog.solidsoft.pl/2020/03/18/places-where-you-really-need-to-use-assert-keyword-in-spock-assertions/</link>
        <pubDate>Wed, 18 Mar 2020 10:00:00 +0200</pubDate>
        
        <atom:modified>Sun, 26 Dec 2021 23:50:00 +0100</atom:modified>
        <guid>https://blog.solidsoft.pl/2020/03/18/places-where-you-really-need-to-use-assert-keyword-in-spock-assertions/</guid>
        <description>Make sure you know all the places where putting the &amp;lsquo;assert&amp;rsquo; keyword in Spock is necessary to avoid false sense of security and tests which - effectively - do nothing.
  Introduction Spock greatly simplifies test creation. One of the improvements is an ability to skip the assert keyword in the verification block (then or expect). It is very convenient, but Spock newcomers (and based on my code testing training also even more experienced developers) might not be aware that under some circumstances that keyword is required, making - as a result - that particular test useless.</description>
        <content:encoded>&lt;blockquote&gt;
&lt;p&gt;Make sure you know all the places where putting the &amp;lsquo;assert&amp;rsquo; keyword in Spock is necessary to avoid false sense of security and tests which - effectively - do nothing.&lt;/p&gt;
&lt;/blockquote&gt;


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

&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Spock greatly simplifies test creation. One of the improvements is an ability to skip the &lt;code&gt;assert&lt;/code&gt; keyword in the verification block (&lt;code&gt;then&lt;/code&gt; or &lt;code&gt;expect&lt;/code&gt;). It is very convenient, but Spock newcomers (and based on my &lt;a href=&#34;https://blog.solidsoft.pl/training/automatic-code-testing-java-spock-junit5/&#34;&gt;code testing training&lt;/a&gt;
 also even more experienced developers) might not be aware that under some circumstances that keyword is required, making - as a result - that particular test useless. After lecture of this blog post you will know the places (situations) where the &lt;code&gt;assert&lt;/code&gt; keyboard is mandatory.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s start from the beginning.&lt;/p&gt;
&lt;h2 id=&#34;power-assertions&#34;&gt;Power assertions&lt;/h2&gt;
&lt;p&gt;Power assertions is an advanced assertion mechanism which renders the failed assertion in a very meaningful way. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#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;k&#34;&gt;assert&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;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&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;mi&#34;&gt;4&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;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;results in:&lt;/p&gt;
&lt;div class=&#34;highlight&#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;Assertion&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;failed:&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;assert&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;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&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;mi&#34;&gt;4&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;mi&#34;&gt;3&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4&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;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;mi&#34;&gt;5&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;  &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;    &lt;span class=&#34;mi&#34;&gt;20&lt;/span&gt;   &lt;span class=&#34;mi&#34;&gt;12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is a great step forward over the classic &lt;code&gt;assertEquals()&lt;/code&gt; assertion with just &lt;code&gt;Assertion failed&lt;/code&gt; in JUnit.&lt;/p&gt;
&lt;p&gt;What is nice, it works also for objects and method calls:&lt;/p&gt;
&lt;div class=&#34;highlight&#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;Assertion&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;failed:&lt;/span&gt; 

&lt;span class=&#34;k&#34;&gt;assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ann&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bob&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ann&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;age&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;bob&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;age&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;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;Ann&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;Bob&lt;/span&gt;  &lt;span class=&#34;kc&#34;&gt;false&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;Person&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nl&#34;&gt;name:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Bob&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;age:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;7&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;kc&#34;&gt;false&lt;/span&gt;
       &lt;span class=&#34;n&#34;&gt;Person&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nl&#34;&gt;name:&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Ann&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nl&#34;&gt;age:&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;4&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Power assertions have been developed initially for Spock, but later on they were backported to Groovy 1.7 (2009). Currently, they are one of the killer &lt;a href=&#34;https://groovy-lang.org/testing.html#_power_assertions&#34; target=&#34;_blank&#34;&gt;features of Groovy&lt;/a&gt;
 in the context of testing (in general, not only with Spock).&lt;/p&gt;
&lt;h2 id=&#34;optional-assert&#34;&gt;Optional &amp;lsquo;assert&amp;rsquo;&lt;/h2&gt;
&lt;p&gt;As I already mentioned in the introduction, Spock using the Groovy magic (primarily AST transformations and operator overloading) generates and automatically handles different aspect of tests to make its creation as simple as possible. Among others, it is visible in exception testing - a hidden &lt;code&gt;try..catch&lt;/code&gt; around the &lt;code&gt;when&lt;/code&gt; block or implicit method arguments in parameterized tests.&lt;/p&gt;
&lt;p&gt;Another case for simplification in an optional &lt;code&gt;assert&lt;/code&gt; keyword with assertions. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#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;o&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;nl&#34;&gt;expect:&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;numberOfItems&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;can be simplified to just:&lt;/p&gt;
&lt;div class=&#34;highlight&#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;o&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;nl&#34;&gt;expect:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;numberOfItems&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;assert&lt;/code&gt; keyword is automatically added by the Spock AST transformation in the &lt;code&gt;then&lt;/code&gt; or &lt;code&gt;expect&lt;/code&gt; blocks, if there is a boolean value, but also any non-void statement which can be evaluated with &lt;a href=&#34;https://groovy-lang.org/semantics.html#Groovy-Truth&#34; target=&#34;_blank&#34;&gt;The Groovy Truth&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;This opens different possibilities:&lt;/p&gt;
&lt;div class=&#34;highlight&#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;o&#34;&gt;...&lt;/span&gt; 
&lt;span class=&#34;nl&#34;&gt;when:&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;Invoiced&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;overdueInvoices&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;userAccount&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getOverdueIncoives&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;overdueInvoices&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;//collection cannot be null or empty to not to fail
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Under the hood, the Spock AST transformation detects all those places to enhance them with &lt;code&gt;assert&lt;/code&gt;, but there are some limitations.&lt;/p&gt;
&lt;h2 id=&#34;required-assert&#34;&gt;Required &amp;lsquo;assert&amp;rsquo;&lt;/h2&gt;
&lt;div class=&#34;notices warning&#34; &gt;
  There are places (situations) where &lt;code&gt;assert&lt;/code&gt; cannot be omitted. It is especially crucial to know them as there is no error displayed. The assertions &lt;strong&gt;just do not work&lt;/strong&gt; which makes them useless. Or event worse, it &lt;strong&gt;gives a false sense of security&lt;/strong&gt; - those tests do not test anything.
&lt;/div&gt;
&lt;h3 id=&#34;guard-assertion&#34;&gt;Guard assertion&lt;/h3&gt;
&lt;p&gt;The first case is so-called guard assertion. Occasionally, mostly in integration/acceptance testing there is a need to check the initial state (e.g. number of records in a database to ensure than some previously added new - badly written - test did not break our test data).&lt;/p&gt;
&lt;p&gt;Spock cares only about &lt;code&gt;then&lt;/code&gt; and &lt;code&gt;expect&lt;/code&gt; blocks in the context of the implicit &lt;code&gt;assert&lt;/code&gt;. The &lt;code&gt;assert&lt;/code&gt; keyword is not automatically added in the &lt;code&gt;given&lt;/code&gt; block and has to be placed manually.&lt;/p&gt;
&lt;div class=&#34;highlight&#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;nl&#34;&gt;given:&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;Invoice&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;initialInvoices&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;legacyRepository&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getUserInvoices&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;USER_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;  
    &lt;span class=&#34;k&#34;&gt;assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;initialInvoices&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;size&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;c1&#34;&gt;//&amp;#39;assert&amp;#39; is mandatory - &amp;#39;initialInvoices.size() == 0&amp;#39; does nothing!
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nl&#34;&gt;when:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;issueInvoice&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;legacyRepository&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;getUserInvoices&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;USER_ID&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;size&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;1&lt;/span&gt;   &lt;span class=&#34;c1&#34;&gt;//&amp;#39;assert&amp;#39; is not needed in &amp;#39;then&amp;#39; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;assertion-in-method-execution&#34;&gt;Assertion in method execution&lt;/h3&gt;
&lt;p&gt;The another situation refers to the &lt;code&gt;then&lt;/code&gt; (or &lt;code&gt;expect&lt;/code&gt;) block. Sometimes there is a set of assertions that is used in more than one tests. It might be handy to extract them to a separate method (placed locally in the test class, in a super class, or in a trait):&lt;/p&gt;
&lt;div class=&#34;highlight&#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;nl&#34;&gt;when:&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;assertCompatibilityWithArticle17OfEUDirective&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;socialMediaSubmission&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;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;void&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;assertCompatibilityWithArticle17OfEUDirective&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SocialMediaSubmission&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;submission&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;k&#34;&gt;assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;submission&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;field1&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;//&amp;#39;assert&amp;#39; is mandatory 
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;k&#34;&gt;assert&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;submission&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;field2&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;/div&gt;&lt;p&gt;For Spock, method call is treated as a regular value to be evaluated (if method is non-void). Therefore, if a method returns &lt;code&gt;false&lt;/code&gt; or &lt;code&gt;0&lt;/code&gt; or an empty collection the test fails. Otherwise, also if a method has the &lt;code&gt;void&lt;/code&gt; return type, the test passes.&lt;/p&gt;
&lt;p&gt;It is requires to care about the assertions manually, but placing the &lt;code&gt;assert&lt;/code&gt; keyword explicitly withing the method.&lt;/p&gt;
&lt;h3 id=&#34;assertion-in-closure-execution&#34;&gt;Assertion in Closure execution&lt;/h3&gt;
&lt;p&gt;A similar class of problems poses assertions within closures. They might be not so often used as in methods, but it makes them even more at risk of incorrect usage.&lt;/p&gt;
&lt;div class=&#34;highlight&#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;o&#34;&gt;...&lt;/span&gt;
&lt;span class=&#34;nl&#34;&gt;expect:&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;GParsPool&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;withPool&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;1&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;eachParallel&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;CorrelationIdUpdater&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;wrapClosureWithId&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;assert&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;s2&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//mandatory &amp;#34;assert&amp;#34;
&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;o&#34;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With Groovy 3 (and &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-M2+&lt;/a&gt;
) the same applies to assertions in lambda expressions.&lt;/p&gt;
&lt;h3 id=&#34;other-cases&#34;&gt;Other cases&lt;/h3&gt;
&lt;p&gt;Quoting the &lt;a href=&#34;https://spockframework.org/spock/docs/2.0/all_in_one.html#_implicit_and_explicit_conditions&#34; target=&#34;_blank&#34;&gt;Spock documentation&lt;/a&gt;
:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Conditions are an essential ingredient of then blocks and expect blocks. Except for calls to void methods and expressions classified as interactions, all top-level expressions in these blocks are implicitly treated as conditions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, in addition to the 3 aforementioned cases, anything not &amp;ldquo;top-level&amp;rdquo; (or not placed in the &lt;code&gt;then&lt;/code&gt; and &lt;code&gt;expect&lt;/code&gt; blocks) should bring our attention. That includes - less popular - conditional statements (&lt;code&gt;if/else&lt;/code&gt;), loops, and the &lt;code&gt;catch&lt;/code&gt; blocks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Updated 2021-12-26&lt;/strong&gt;. Added the &amp;ldquo;Other cases&amp;rdquo; section, based on a constructive comment by &lt;a href=&#34;https://github.com/szpak/blog.solidsoft.pl-comments/issues/7#issuecomment-994562701&#34; target=&#34;_blank&#34;&gt;Hari Krishna Dara&lt;/a&gt;
.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Spock and Groovy (as every tool or language) can be used in more or less &amp;ldquo;messy way&amp;rdquo;. Groovy being a very flexible and optionally dynamic language makes it even easier. &amp;ldquo;With great power comes great responsibility&amp;rdquo;, a proverb popularized by the Spider-Man franchise, can be applied also to Spock. Users should be aware of the limitations and corner cases to avoid mistakes.&lt;/p&gt;
&lt;p&gt;Btw, in the context of assertions those are corner cases where assertion(-like) expression is just ignored, which is much worse than just an error. However, it is not the only place. A few years ago I made a 50-minutes long &lt;a href=&#34;https://blog.solidsoft.pl/talks/2016-06-01-nooks-and-crannies-of-spock-gr8conf/&#34;&gt;presentations&lt;/a&gt;
 just about &amp;ldquo;Interesting nooks and crannies of Spock&amp;rdquo; (&lt;a href=&#34;https://blog.solidsoft.pl/talks/2016-06-01-nooks-and-crannies-of-spock-gr8conf/&#34;&gt;slides and videos&lt;/a&gt;
). And definitely I didn&amp;rsquo;t exhausted a topic :-).&lt;/p&gt;
&lt;span style=&#34;opacity: 0.6&#34;&gt;Lead photo based on unofficial Spock logo &lt;a href=&#34;https://github.com/spockframework/spock/pull/34&#34;&gt;proposal&lt;/a&gt; from 2014 by &lt;a href=&#34;https://github.com/sbglasius&#34;&gt;Søren Berg Glasius&lt;/a&gt; and work safety signs by &lt;a href=&#34;https://pixabay.com/users/Clker-Free-Vector-Images-3736/&#34;&gt;Clker-Free-Vector-Images&lt;/a&gt;, published in &lt;a href=&#34;https://pixabay.com/vectors/eye-protection-mandatory-sign-24091/&#34;&gt;Pixabay&lt;/a&gt;.&lt;/span&gt;
</content:encoded>
        <dc:creator>Marcin Zajączkowski</dc:creator>
        <media:content url="https://blog.solidsoft.pl//images/posts/2020/spock-assert-mandatory-thumbnail.png" medium="image"><media:title type="html">featured image</media:title></media:content>
        
        <media:content url="https://blog.solidsoft.pl//images/posts/2020/spock-assert-mandatory-ratio.png" medium="image"><media:title type="html">meta image</media:title></media:content>
        
          
            
              <category>spock</category>
            
          
            
              <category>pitfall</category>
            
          
            
              <category>testing</category>
            
          
            
              <category>tests</category>
            
          
            
              <category>groovy</category>
            
          
        
        
          
            
              <category>Tools</category>
            
          
        
        
      </item>
      
      <item>
        <title>Simplify integration testing of legacy applications with Spock 1.2</title>
        <link>https://blog.solidsoft.pl/2018/09/14/simplify-integration-testing-of-legacy-applications-with-spock-1.2/</link>
        <pubDate>Fri, 14 Sep 2018 10:00:00 +0200</pubDate>
        
        <atom:modified>Fri, 14 Sep 2018 10:00:00 +0200</atom:modified>
        <guid>https://blog.solidsoft.pl/2018/09/14/simplify-integration-testing-of-legacy-applications-with-spock-1.2/</guid>
        <description>Learn how leverage Spock 1.2 to slice a Spring context of a legacy application writing integration tests.
 Have you ever wanted, having some legacy application which you were starting to work on, to write some tests to get know what is going on and possibly be notified about regressions? That feeling when you want to instantiate a single class and it fails with NullPointerException. 6 replaced (with difficulty) dependencies later there are still some errors from the classes that you haven&amp;rsquo;t heard about before.</description>
        <content:encoded>&lt;blockquote&gt;
&lt;p&gt;Learn how leverage Spock 1.2 to slice a Spring context of a legacy application writing integration tests.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Have you ever wanted, having some legacy application which you were starting to work on, to write some tests to get know what is going on and possibly be notified about regressions? That feeling when you want to instantiate a single class and it fails with &lt;code&gt;NullPointerException&lt;/code&gt;. 6 replaced (with difficulty) dependencies later there are still some errors from the classes that you haven&amp;rsquo;t heard about before. Sounds familiar?&lt;/p&gt;
&lt;p&gt;There are different techniques to deal with hidden dependencies. There is the whole dedicated &lt;a href=&#34;https://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052&#34; target=&#34;_blank&#34;&gt;book&lt;/a&gt;
 about that (and probably a few other that I haven&amp;rsquo;t read). Occasionally, it may be feasible to start with the integration tests and run through some process. It may be even more &amp;ldquo;entertaining&amp;rdquo; to see what exotic components are required to just setup the context, even if they are completely not needed in our case. Thank you (too wide and carelessly used) &lt;code&gt;@ComponentScan&lt;/code&gt; :).&lt;/p&gt;
&lt;p&gt;Injecting stubs/mocks inside the test context is a way to go as an emergency assistance (see the last paragraph, there are better, yet harder approaches). It can be achieved &amp;ldquo;manually&amp;rdquo; with an extra bean definition with the &lt;code&gt;@Primary&lt;/code&gt; annotation (usually a reason to think twice before doing that) for every dependency at which level we want to make a cut of (or for every unneeded bean which is instantiated by the way). &lt;code&gt;@MockBean&lt;/code&gt; placed on a field in a test is more handy, but still, it is needed to define a field in our tests and put the annotation on it (5? 10? 15 beans?). Spock 1.2 introduces somehow less know feature which may be useful here - &lt;code&gt;@StubBeans&lt;/code&gt;.&lt;/p&gt;




  



  &lt;div class=&#34;featured-image__wrapper&#34;&gt;
    &lt;img src=&#34;https://blog.solidsoft.pl/images/posts/2018/mocked-dependencies-spring.png&#34; alt=&#34;Featured Image&#34; class=&#34;featured-image&#34; style=&#34;width: 680px;height: 356px;&#34;&gt;
  &lt;/div&gt;

&lt;p&gt;It can be used to simply provide a list of classes which (possible) instances should be replaced with stubs in the Spring test context. Of course before the real objects are being instantiated (to prevent for example NPE in a constructor). Thanks to that up to several lines of stubbing/mock injections:&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;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;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;22
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;23
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;24
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;25
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;26
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;27
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;28
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;29
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;30
&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;@RunWith&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;SpringRunner&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;c1&#34;&gt;//Spring Boot + Mockito
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@SpringBootTest&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;//possibly some Spring configuration with @ComponentScan is imported in this legacy application
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;BasicPathReportGeneratorInLegacyApplicationITTest&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;//usual approach
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@MockBean&lt;/span&gt;
    &lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;KafkaClient&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;kafkaClientMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;nd&#34;&gt;@MockBean&lt;/span&gt;
    &lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FancySelfieEnhancer&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fancySelfieEnhancerMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;nd&#34;&gt;@MockBean&lt;/span&gt;
    &lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FastTwitterSubscriber&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fastTwitterSubscriberMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;nd&#34;&gt;@MockBean&lt;/span&gt;
    &lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WaterCoolerWaterLevelAterter&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;waterCoolerWaterLevelAterterMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;nd&#34;&gt;@MockBean&lt;/span&gt;
    &lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NsaSilentNotifier&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;nsaSilentNotifierMock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;;&lt;/span&gt;

    &lt;span class=&#34;c1&#34;&gt;//a few more - remember, this is legacy application, genuine since 1999 ;)
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;c1&#34;&gt;//...
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@Autowired&lt;/span&gt;
    &lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ReportGenerator&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reportGenerator&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;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;shouldGenerateEmptyReportForEmptyInputData&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;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;can be replaced with just one (long) line:&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-groovy&#34; data-lang=&#34;groovy&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@SpringBootTest&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;//possibly some Spring configuration with @ComponentScan is imported
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nd&#34;&gt;@StubBeans&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;([&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;KafkaClient&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FancySelfieEnhancer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FastTwitterSubscriber&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;WaterCoolerWaterLevelAterter&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NsaSilentNotifier&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;/(, ... */&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;])&lt;/span&gt;
  &lt;span class=&#34;c1&#34;&gt;//all classes of real beans which should be replaced with stubs
&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;BasicPathReportGeneratorInLegacyApplicationITSpec&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;nd&#34;&gt;@Autowired&lt;/span&gt;
    &lt;span class=&#34;kd&#34;&gt;private&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ReportGenerator&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reportGenerator&lt;/span&gt;

    &lt;span class=&#34;kt&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;should generate empty report for empty input data&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;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;(tested with Spock 1.2-RC2)&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s worth to mention that &lt;code&gt;@StubBeans&lt;/code&gt; is intended just to provide placeholders. In a situation it is required to provide stubbing and/or an invocation verification &lt;code&gt;@SpringBean&lt;/code&gt; or &lt;code&gt;@SpringSpy&lt;/code&gt; (also introduced in Spock 1.2) are better. I wrote more about it in my previous &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;blog post&lt;/a&gt;
.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;There is one important aspect to emphasize&lt;/strong&gt;. &lt;code&gt;@StubBeans&lt;/code&gt; are handy to be used in a situation when we have some &amp;ldquo;legacy&amp;rdquo; project and want to start writing integration regression tests quickly to see the results. However, as a colleague of mine &lt;a href=&#34;https://stackoverflow.com/users/719633/roadrunner&#34; target=&#34;_blank&#34;&gt;Darek Kaczyński&lt;/a&gt;
 brightly summarized, blindly replacing beans which &amp;ldquo;explode&amp;rdquo; in tests is just &amp;ldquo;sweeping problems under carpet&amp;rdquo;. After the initial phase, when we are starting to understand what is going on, it is a good moment to rethink the way the context - both in production and in tests - is created. The already mentioned too wide &lt;code&gt;@ComponentScan&lt;/code&gt; is very often the root of all evil. An ability to setup a partial context and put it together (if needed) is a good place to start. Using &lt;code&gt;@Profile&lt;/code&gt; or conditional beans are the very powerful mechanisms in tests (and not only there). &lt;code&gt;@TestConfiguration&lt;/code&gt; and proper bean selection to improve context caching are something worth to keep in your mind. However, I started this article to present the new mechanism in Spock which might be useful in some cases and I want to keep it short. There could be an another, more generic blog post just about managing the Spring context in the integration tests. I have to seriously thing about it :).&lt;/p&gt;
</content:encoded>
        <dc:creator>Marcin Zajączkowski</dc:creator>
        <media:content url="https://blog.solidsoft.pl/images/posts/2018/mocked-dependencies-spring.png" medium="image"><media:title type="html">featured image</media:title></media:content>
        
        
        
          
            
              <category>groovy</category>
            
          
            
              <category>integration-testing</category>
            
          
            
              <category>mocking</category>
            
          
            
              <category>mockito</category>
            
          
            
              <category>spock</category>
            
          
            
              <category>spock-1.2</category>
            
          
            
              <category>spring</category>
            
          
            
              <category>spring-boot</category>
            
          
            
              <category>testing</category>
            
          
            
              <category>tests</category>
            
          
        
        
          
            
              <category>Tools</category>
            
          
            
              <category>Tricks &amp; Tips</category>
            
          
        
        
      </item>
      

    
  </channel>
</rss>