<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://feeds.feedblitz.com/feedblitz_rss.xslt"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	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:slash="http://purl.org/rss/1.0/modules/slash/"
	 xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
<channel>
	<title>Petri Kainulainen</title>
	<atom:link href="https://www.petrikainulainen.net/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.petrikainulainen.net/</link>
	<description>Developing Software With Passion</description>
	<lastBuildDate>Tue, 11 Aug 2026 06:11:31 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.4</generator>
<meta xmlns="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
<item>
<feedburner:origLink>https://www.petrikainulainen.net/monthly/software-development-monthly-7-2026/</feedburner:origLink>
		<title>Software Development Monthly 7 / 2026</title>
		<link>https://feeds.feedblitz.com/~/967650665/0/petrikainulainen~Software-Development-Monthly/</link>
					<comments>https://feeds.feedblitz.com/~/967650665/0/petrikainulainen~Software-Development-Monthly/#respond</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Tue, 11 Aug 2026 06:11:31 +0000</pubDate>
				<category><![CDATA[Monthly]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Clean Code]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Software Development]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=29550</guid>
					<description><![CDATA[<p>The Software Development Monthly is a monthly blog post that highlights interesting or useful blog posts which I read during the previous month. This blog post shares 17 interesting or useful blog posts which I read during July 2026. <a rel="NOFOLLOW" class="excerpt_read_more" href="/monthly/software-development-monthly-7-2026/">Read More</a></p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/967650665/0/petrikainulainen~Software-Development-Monthly/">Software Development Monthly 7 / 2026</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/967650665/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/967650665/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/967650665/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/967650665/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p>The Software Development Monthly is a monthly blog post that shares interesting or useful content which I consumed during the previous month. This blog post is always published on the eighth day of the month.</p>
<p>Let's begin!</p>
<div class="note">
<strong>Table of Contents:</strong></p>
<ul>
<li><a href="#ai">AI</a></li>
<li><a href="#sw-development">Software Development</a></li>
</ul>
</div>
<h2 id="ai">AI</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://piotrminkowski.com/2026/07/02/continuous-development-with-claude-code-on-github/">Continuous Development with Claude Code on GitHub</a> demonstrates how we can use the Claude GitHub App and Claude Code for implementing features and reviewing PRs.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://larsfaye.com/articles/ai-coding-will-prevent-expertise">AI Coding will Prevent Expertise</a> warns that heavy reliance on AI creates an illusion of competence and argues that true expertise is built through failing and solving hard problems yourself.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://arnon.dk/the-current-ai-pricing-was-always-going-to-go-away/">The current AI pricing was always going to go away</a> explains why subsidized flat-rate AI pricing will eventually be replaced by usage-based billing.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://github.blog/ai-and-ml/github-copilot/better-tools-made-copilot-code-review-worse-heres-how-we-actually-improved-it/">Better tools made Copilot code review worse. Here’s how we actually improved it</a> explains why replacing the code exploration tools of the GitHub Copilot code review agent led to worse reviews and describes how GitHub fixed this problem.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://martinfowler.com/articles/exploring-gen-ai/local-models-for-coding-factors.html">Viability of local models for coding</a> identifies the key factors that determine if running local LLMs for programming is worth it.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://martinfowler.com/articles/exploring-gen-ai/local-models-for-coding-experiences.html">Experiences with local models for coding</a> describes what happened when the author used local LLMs for completing real programming tasks.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.softwaremaxims.com/blog/reviewing-ai-code">Reviewing AI Code Is Not A Viable Argument</a> challenges the belief that humans can effectively review AI-generated code and ensure that only "good code" is merged to main.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://aob2f.substack.com/p/the-ai-hype-is-a-mass-psychosis-echo">The AI hype is a mass psychosis echo chamber of incompetent individuals</a> rants that one of the main reasons behind the AI hype is that AI gives incompetent individuals a false sense of competence.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.hardresetmedia.com/p/the-ai-productivity-illusion">The AI Productivity Illusion</a> explains why generating more things in less time doesn't necessarily increase economic productivity.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://martinfowler.com/articles/exploring-gen-ai/refactoring-economic-benefit.html">The Economic Benefit of Refactoring</a> documents an experiment where the author demonstrated that refactoring AI-generated (and messy) code reduces the future token consumption of AI agents.</p>
<h2 id="sw-development">Software Development</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://martinelli.ch/waterfall-was-never-the-problem/">Waterfall Was Never the Problem</a> argues that waterfall is actually a good choice in certain situations and points out that critics often attack Royce's initial version instead of the final product. Finally, the author explains how AI fixes waterfall's biggest problem.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://foojay.io/today/nulling-out-references-wont-help-your-garbage-collector/">Nulling Out References Won’t Help Your Garbage Collector</a> busts the myth that setting local variables to <code>null</code> helps the JVM garbage collector do its job more efficiently.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://foojay.io/today/when-not-to-use-event-driven-architecture-eda/">When NOT TO USE Event-Driven Architecture (EDA)</a> identifies seven situations where we shouldn't use event-driven architecture because it adds unnecessary complexity and causes issues in production.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.vojtechruzicka.com/owasp-top-10-2025/">OWASP Top 10 2025</a> identifies the new OWASP Top 10 for 2025, compares it to the 2021 list, and analyzes what has changed in web security over the past four years.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://github.blog/engineering/the-cost-of-saying-yes-has-changed/">The cost of saying yes has changed</a> argues that even though AI has dramatically reduced the cost of writing code, the cost of owning, reviewing, and maintaining code hasn't changed.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://martinfowler.com/articles/archaeologist-copilot.html">The Archaeologist’s Copilot</a> explores how software developers can use AI for investigating and modernizing legacy codebases.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://martinfowler.com/rachels-ramblings/conductor-developer.html">The Conductor Developer</a> describes how we are shifting from solo coding to "orchestrating" AI agents and argues that because AI agents write more code, human attention has become the new bottleneck.</p>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/monthly/software-development-monthly-7-2026/">Software Development Monthly 7 / 2026</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/967650665/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/967650665/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/967650665/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/967650665/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/967650665/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/967650665/0/petrikainulainen~Software-Development-Monthly/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments></item>
<item>
<feedburner:origLink>https://www.petrikainulainen.net/uncategorized/new-rss-feed/</feedburner:origLink>
		<title>New RSS Feed</title>
		<link>https://feeds.feedblitz.com/~/967470791/0/petrikainulainen~New-RSS-Feed/</link>
					<comments>https://feeds.feedblitz.com/~/967470791/0/petrikainulainen~New-RSS-Feed/#respond</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Sun, 09 Aug 2026 09:32:26 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=29560</guid>
					<description><![CDATA[<p>I am cancelling my FeedBlitz subscription and transitioning back to the default WordPress RSS feed. If you have subscribed to my RSS feed and want to continue reading my blog posts, you should update the address of my RSS feed. The new address is: https://www.petrikainulainen.net/feed/.</p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/967470791/0/petrikainulainen~New-RSS-Feed/">New RSS Feed</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/967470791/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/967470791/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/967470791/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/967470791/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p>I am cancelling my FeedBlitz subscription and transitioning back to the default WordPress RSS feed. If you have subscribed to my RSS feed and want to continue reading my blog posts, you should update the address of my RSS feed. The new address is: https://www.petrikainulainen.net/feed/.</p>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/uncategorized/new-rss-feed/">New RSS Feed</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/967470791/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/967470791/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/967470791/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/967470791/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/967470791/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/967470791/0/petrikainulainen~New-RSS-Feed/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments></item>
<item>
<feedburner:origLink>https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-7-2026/</feedburner:origLink>
		<title>Clean Test Automation Monthly 7 / 2026</title>
		<link>https://feeds.feedblitz.com/~/966457496/0/petrikainulainen~Clean-Test-Automation-Monthly/</link>
					<comments>https://feeds.feedblitz.com/~/966457496/0/petrikainulainen~Clean-Test-Automation-Monthly/#respond</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Wed, 05 Aug 2026 07:02:09 +0000</pubDate>
				<category><![CDATA[Monthly]]></category>
		<category><![CDATA[Playwright]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Spring Cloud Contract]]></category>
		<category><![CDATA[Spring MockMvc]]></category>
		<category><![CDATA[Spring MVC Test]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=29522</guid>
					<description><![CDATA[<p>The Clean Test Automation Monthly is a monthly blog post that highlights interesting or useful test automation content which I read during the current month. This blog post shares 14 interesting or useful blog posts which I read during July 2026. <a rel="NOFOLLOW" class="excerpt_read_more" href="/monthly/clean-test-automation-monthly-7-2026/">Read More</a></p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/966457496/0/petrikainulainen~Clean-Test-Automation-Monthly/">Clean Test Automation Monthly 7 / 2026</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/966457496/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/966457496/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/966457496/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/966457496/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a><h3 style="clear:left;padding-top:10px">Related Stories</h3><ul><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-7-2025/">Clean Test Automation Monthly 7 / 2025</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-7-2023/">Clean Test Automation Monthly 7 / 2023</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-7-2024/">Clean Test Automation Monthly 7 / 2024</a></li></ul>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p>The Clean Test Automation Monthly is a monthly blog post that shares interesting or useful test automation content that I consumed during the current month. This blog post is always published on the first day of the "next" month.</p>
<p>Let's begin!</p>
<div class="note">
<strong>Table of Contents:</strong></p>
<ul>
<li><a href="#design">Test  Design</a></li>
<li><a href="#backend">Backend</a></li>
<li><a href="#ui-end-to-end">UI / End-to-End</a></li>
</ul>
</div>
<h2 id="design">Test Design</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://testingil.com/2026/07/test-the-feature-now-with-examples.html">Test The Feature: Now With Examples</a> provides code examples which demonstrate why end-to-end tests should concentrate on testing features instead of single API endpoints.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://levelup.gitconnected.com/your-ai-generated-400-tests-they-all-pass-none-of-them-catch-the-bug-that-ships-to-production-95ce0e25fe8f">Your AI Generated 400 Tests. They All Pass. None of Them Catch the Bug That Ships to Production.</a> identifies the pros and cons of AI generated tests, explains why AI generated tests can create false confidence, and describes how we can solve this issue by using better prompts and doing mutation testing.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://aiqualityengineer.cc/your-test-automation-may-be-revealing-team-problems-5e16d498958f">Your Test Automation May Be Revealing Team Problems</a> explains how test automation issues such as fragile tests and knowledge silos can be caused by organizational problems like poor collaboration and weak onboarding.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://medium.com/@sebastien.gineste/stop-mocking-everything-the-3-tests-i-start-with-for-a-service-599954d57e12">Stop Mocking Everything: The 3 Tests I Start With for a Service</a> argues that we should stop mocking everything and introduces a three-test strategy that helps us write (or generate) better tests that test the behavior, not the implementation.</p>
<h2 id="backend">Backend</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://toomuchcoding.com/post/2026-07-06-spring-cloud-contract-becomes-stubborn/">Spring Cloud Contract Is Coming Home: Introducing Stubborn Contract</a> announces that Spring Cloud Contract is transitioning out of the Spring Cloud portfolio. The original author of the project will continue to support it under the name Stubborn Contract. This blog post identifies the reasons behind the change and explains what current users can expect during the migration.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.wimdeblauwe.com/blog/2026/07/07/testing-oauth2-client-login-with-mock-oauth2-server/">Testing OAuth2 client login with mock-oauth2-server</a> is a practical guide that helps us to write tests for Spring Boot OAuth2 client authentication. It explains how we can start a lightweight OAuth2 server when our integration tests are run and write tests for authentication flows without relying on external providers or heavy Docker containers like Keycloak.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.baeldung.com/spring-mvc-handlerinterceptor-test">Testing Spring MVC HandlerInterceptor</a> provides a quick introduction to the <code>HandlerInterceptor</code> interface, describes how we can implement and register a custom <code>HandlerInterceptor</code>, and explains how we can write automated tests for our implementation.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/programming/testing/introduction-to-spring-mvc-test-framework/">Introduction to Spring MockMvc</a> is a complete introduction to Spring MockMvc. It highlights the benefits of Spring MockMvc, identifies its key components, and describes how we can get the required dependencies with Maven and Gradle.</p>
<h2 id="ui-end-to-end">UI / End-to-End</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://laxminarayanaboga.github.io/articles/scaling-playwright-bdd.html">Scaling Playwright‑BDD to 3,000+ Tests Without Losing Your Mind</a> identifies six patterns that help us to write large BDD test suites that are both fast and maintainable.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://laxminarayanaboga.github.io/articles/scalable-test-data-management.html">Highly Scalable Test Data Management in Playwright</a> describes how we can manage the test data of our Playwright tests by using fixtures.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://medium.com/@testdino/what-to-check-when-your-playwright-test-passes-locally-but-fails-in-ci-and-your-screenshot-is-f4e8f6453f4e">What to Check When Your Playwright Test Passes Locally But Fails in CI</a> explains why Playwright tests can fail in CI environments with blank screenshots and provides a step-by-step process that helps us to debug these failing tests.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://josephward.tech/2026-06-30-why-simple-ui-tests-become-slow/">Why Simple UI Tests Become Slow</a> identifies some of the problems which slow down our UI tests and provides tips that help us to optimize the performance of our UI tests.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://medium.com/@pritamkundu.pk5/page-object-model-is-not-enough-the-4-layers-real-frameworks-use-d235829c325c">Page Object Model Is Not Enough: The 4 Layers Real Frameworks Use</a> explains why using only the page object model is insufficient for large test suites and describes how we can write maintainable tests by implementing a four-layer test automation framework.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://vitalets.github.io/posts/playwright-in-pictures/how-fixtures-work/">Playwright in Pictures: How Fixtures Work</a> is a comprehensive tutorial which uses timeline charts to explain how Playwright fixtures work.</p>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-7-2026/">Clean Test Automation Monthly 7 / 2026</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/966457496/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/966457496/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/966457496/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/966457496/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/966457496/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a><h3 style="clear:left;padding-top:10px">Related Stories</h3><ul><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-7-2025/">Clean Test Automation Monthly 7 / 2025</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-7-2023/">Clean Test Automation Monthly 7 / 2023</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-7-2024/">Clean Test Automation Monthly 7 / 2024</a></li></ul>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/966457496/0/petrikainulainen~Clean-Test-Automation-Monthly/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments></item>
<item>
<feedburner:origLink>https://www.petrikainulainen.net/programming/testing/introduction-to-spring-mvc-test-framework/</feedburner:origLink>
		<title>Introduction to Spring MockMvc</title>
		<link>https://feeds.feedblitz.com/~/605931460/0/petrikainulainen~Introduction-to-Spring-MockMvc/</link>
					<comments>https://feeds.feedblitz.com/~/605931460/0/petrikainulainen~Introduction-to-Spring-MockMvc/#comments</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Thu, 30 Jul 2026 16:12:30 +0000</pubDate>
				<category><![CDATA[Testing]]></category>
		<category><![CDATA[Spring MockMvc]]></category>
		<category><![CDATA[Spring MVC Test]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=21386</guid>
					<description><![CDATA[<p>This blog post is a complete introduction to Spring MockMvc. It highlights the benefits of Spring MockMvc, identifies its key components, and describes how we can get the required dependencies with Maven and Gradle. <a rel="NOFOLLOW" class="excerpt_read_more" href="/programming/testing/introduction-to-spring-mvc-test-framework/">Read More</a></p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/605931460/0/petrikainulainen~Introduction-to-Spring-MockMvc/">Introduction to Spring MockMvc</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/605931460/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/605931460/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/605931460/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/605931460/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a><h3 style="clear:left;padding-top:10px">Related Stories</h3><ul><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/programming/testing/writing-unit-test-with-mockmvctester-returning-an-object-as-json/">Writing Unit Test With MockMvcTester: Returning an Object as JSON</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/programming/testing/writing-unit-tests-with-mockmvctester-returning-a-list-as-json/">Writing Unit Tests With MockMvcTester: Returning a List as JSON</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/programming/testing/introduction-to-mockmvctester/">Introduction to MockMvcTester</a></li></ul>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p>This blog post is the first part of my <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/spring-mvc-test-tutorial/">Spring MockMvc tutorial</a>. This tutorial describes how we can write unit and integration tests for Spring MVC controllers by using Spring Boot 4, Spring Framework 7, and JUnit Jupiter. However, before we can write any test code, we have to understand the basics.</p>
<p>After we have finished this blog post, we:</p>
<ul>
<li>Understand what Spring MockMvc is.</li>
<li>Can identify the key components of Spring MockMvc.</li>
<li>Know how we can get the required dependencies with Maven and Gradle.</li>
</ul>
<p>Let's begin.</p>
<h2>What Is Spring MockMvc?</h2>
<p>Spring MockMvc is a testing tool which provides support for testing Spring MVC controllers. The benefits of Spring MockMvc are:</p>
<ul>
<li><strong>No Web Server Required</strong>. Because Spring MockMvc is built on top of the Servlet API mock objects provided by the <code>spring-test</code> module, it doesn't require a servlet container and the tests which use it bypass the network layer. Thus, our tests are as fast as possible.</li>
<li><strong>Full Spring MVC Runtime Support</strong>. Because Spring MockMvc uses the <code>DispatcherServlet</code> class that provides full support for the Spring MVC runtime behavior, we can test real request mappings, parameter binding, request validation, error handling, and JSON serialization/deserialization.</li>
<li><strong>Test Framework Agnostic</strong>. We can write our tests by using JUnit 4, JUnit 5, or TestNG. We can also use other testing frameworks as long as the testing framework provides support for Spring MockMvc or we use the standalone configuration.</li>
<li><strong>Flexible Test Configuration</strong>. We can configure the system under test by using a lightweight standalone configuration, a focused test slice (<code>@WebMvcTest</code>), or a web application context based configuration. We will talk more about these configuration options in the next posts of this tutorial.</li>
<li><strong>Flexible Assertion Support</strong>. We can write assertions by using Spring's <code>MockMvcResultMatchers</code> (together with Hamcrest or JSONPath), write assertions for the <code>MvcResult</code> object by using our favorite assertion library, or leverage the fluent <code>MockMvcTester</code> API and write our assertions with AssertJ.</li>
</ul>
<div class="note">Spring MockMvc doesn't send real HTTP requests to the system under test. All tests are run in a mock environment provided by Spring MockMvc.</div>
<p>Next, we will take a look at the key components of Spring MockMvc.</p>
<h2>The Key Components of Spring MockMvc</h2>
<p>Spring MockMvc provides two main styles for writing tests:</p>
<ul>
<li>The Classic <code>MockMvc</code> API which uses static factory methods.</li>
<li>The Modern <code>MockMvcTester</code> API which was introduced in Spring Framework 6.2 / Spring Boot 3.4. The <code>MockMvcTester</code> API provides a fluent API for sending HTTP requests to the system under test and integrates Spring MockMvc with AssertJ.</li>
</ul>
<div class="note">I use the terms: "HTTP request" and "HTTP response" in this blog post because it makes things a bit easier to understand. You should remember that Spring MockMvc doesn't send real HTTP requests to the system under test. All tests are run in a mock environment provided by Spring MockMvc.</div>
<p>Let's move on and take a look at the core components of both styles.</p>
<h3>The Classic MockMvc API</h3>
<p>If we use the traditional <code>MockMvc</code> API, our tests will interact with the following key classes:</p>
<ul>
<li>The <code>MockMvc</code> class acts as an entry point for our unit and integration tests. To be more specific, we will use this class when we send HTTP requests to the system under test.</li>
<li>The <code>MockMvcBuilders</code> class provides <code>static</code> factory methods which allow us to create new <code>MockMvc</code> objects.</li>
<li>The <code>MockMvcRequestBuilders</code> class provides <code>static</code> factory methods which we can use for creating the HTTP requests sent to the system under test.</li>
<li>The <code>MockMvcResultMatchers</code> class provides <code>static</code> factory methods which allow us to write assertions for the returned HTTP response.</li>
<li>The <code>MockMvcResultHandlers</code> class provides <code>static</code> factory methods which we can use when we want to print the returned HTTP response or write the HTTP response to a log file by using the Apache Commons Logging library.</li>
</ul>
<div class="note"><strong>Additional Reading:</strong></p>
<ul>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/web/servlet/MockMvc.html">The Javadoc of the <code>MockMvc</code> class</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/web/servlet/setup/MockMvcBuilders.html">The Javadoc of the <code>MockMvcBuilders</code> class</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.html">The Javadoc of the <code>MockMvcRequestBuilders</code> class</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/web/servlet/result/MockMvcResultMatchers.html">The Javadoc of the <code>MockMvcResultMatchers</code> class</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/web/servlet/result/MockMvcResultHandlers.html">The Javadoc of the <code>MockMvcResultHandlers</code> class</a></li>
</ul>
</div>
<h3>The Modern MockMvcTester API</h3>
<p>If we use the modern <code>MockMvcTester</code> API, our tests will interact with the following key classes:</p>
<ul>
<li>The <code>MockMvcTester</code> class is built on top of the <code>MockMvc</code> API. It provides a fluent API for building HTTP requests and sending them to the system under test.</li>
<li>The <code>MvcTestResult</code> class contains the result of an executed HTTP request that was built with the <code>MockMvcTester</code> API. We can write assertions for the HTTP response by invoking the <code>assertThat()</code> method and passing the <code>MvcTestResult</code> object as a method parameter.</li>
<li>The <code>MvcTestResultAssert</code> class implements the AssertJ assertions which we can use when we are writing assertions for the returned HTTP response.</li>
</ul>
<div class="note"><strong>Additional Reading:</strong></p>
<ul>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/web/servlet/assertj/MockMvcTester.html">The Javadoc of the <code>MockMvcTester</code> class</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/web/servlet/assertj/MvcTestResult.html">The Javadoc of the <code>MvcTestResult</code> class</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.spring.io/spring-framework/docs/7.0.x/javadoc-api/org/springframework/test/web/servlet/assertj/MvcTestResultAssert.html">The Javadoc of the <code>MvcTestResultAssert</code> class</a></li>
</ul>
</div>
<p>Let's move on and find out how we can get the required dependencies with Maven and Gradle.</p>
<h2>Getting the Required Dependencies</h2>
<p>This section describes how we can get the required dependencies when we declare our dependencies one by one and when we use the dependency management of Spring Boot.</p>
<div class="note">If we are writing a modern Spring Boot application, we should use Spring Boot's dependency management because it will automatically get compatible versions of JUnit Jupiter, AssertJ, Mockito, Hamcrest, and JSONPath.</div>
<h3>Declaring Our Dependencies One by One</h3>
<p>If we are building a standalone Spring application without Spring Boot, we must declare the <code>spring-test</code> dependency in our build script.</p>
<p>If we are using Maven, we can declare this dependency by adding the following snippet to the <code>dependencies</code> section of our <em>pom.xml</em> file:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework&lt;/groupId&gt;
    &lt;artifactId&gt;spring-test&lt;/artifactId&gt;
    &lt;version&gt;7.0.8&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
</pre>
<p>If we are using Gradle, we have to add the <code>spring-test</code> dependency to the <code>testImplementation</code> dependency configuration.</p>
<p>If we are using the Groovy DSL, we have to add the following snippet to the <code>dependencies</code> block of our <em>build.gradle</em> file:</p>
<pre class="brush: groovy; title: ; notranslate">
testImplementation(&#039;org.springframework:spring-test:7.0.8&#039;)
</pre>
<p>If we are using the Kotlin DSL, we have to add the following snippet to the <code>dependencies</code> block of our <em>build.gradle.kts</em> file:</p>
<pre class="brush: groovy; title: ; notranslate">
testImplementation(&quot;org.springframework:spring-test:7.0.8&quot;)
</pre>
<h3>Using the Dependency Management of Spring Boot</h3>
<p>If we use Spring Boot, we only need to declare the <code>spring-boot-starter-test</code> dependency in our build script. The dependency management of Spring Boot will automatically get compatible versions of all essential testing libraries (including JUnit Jupiter, Mockito, AssertJ, and Spring Test).</p>
<p>If we are using Maven, we can declare this dependency by adding the following snippet to the <code>dependencies</code> section of our <em>pom.xml</em> file:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
&lt;/dependency&gt;
</pre>
<p>If we are using Gradle, we have to add the <code>spring-boot-starter-test</code> dependency to the <code>testImplementation</code> dependency configuration.</p>
<p>If we are using the Groovy DSL, we have to add the following snippet to the <code>dependencies</code> block of our <em>build.gradle</em> file:</p>
<pre class="brush: groovy; title: ; notranslate">
testImplementation(&#039;org.springframework.boot:spring-boot-starter-test&#039;)
</pre>
<p>If we are using the Kotlin DSL, we have to add the following snippet to the <code>dependencies</code> block of our <em>build.gradle.kts</em> file:</p>
<pre class="brush: groovy; title: ; notranslate">
testImplementation(&quot;org.springframework.boot:spring-boot-starter-test&quot;)
</pre>
<div class="note">Naturally, a real software project requires other testing dependencies as well. If you want to get more information about the required dependencies, you should take a look at the <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://github.com/pkainulainen/spring-mvc-test-examples/tree/master/junit-5/" target="_blank" rel="noopener noreferrer">example applications of my new Spring MVC Test tutorial</a> (a work in progress).</div>
<p>Let's summarize what we learned from this blog post.</p>
<h2>Summary</h2>
<p>This blog post has taught us five things:</p>
<ul>
<li>Spring MockMvc doesn't require a servlet container and the tests which use it bypass the network layer.</li>
<li>Spring MockMvc provides full support for the Spring MVC runtime behavior because it uses the real <code>DispatcherServlet</code> class behind the scenes.</li>
<li>The classic <code>MockMvc</code> uses static builders and matchers and the modern <code>MockMvcTester</code> provides a fluent API with AssertJ integration.</li>
<li>If we are building a standalone Spring application without Spring Boot, we must declare the <code>spring-test</code> dependency in our build script.</li>
<li>If we use Spring Boot, we only need to declare the <code>spring-boot-starter-test</code> dependency in our build script.</li>
</ul>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/programming/testing/introduction-to-spring-mvc-test-framework/">Introduction to Spring MockMvc</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/605931460/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/605931460/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/605931460/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/605931460/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/605931460/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a><h3 style="clear:left;padding-top:10px">Related Stories</h3><ul><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/programming/testing/writing-unit-test-with-mockmvctester-returning-an-object-as-json/">Writing Unit Test With MockMvcTester: Returning an Object as JSON</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/programming/testing/writing-unit-tests-with-mockmvctester-returning-a-list-as-json/">Writing Unit Tests With MockMvcTester: Returning a List as JSON</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/programming/testing/introduction-to-mockmvctester/">Introduction to MockMvcTester</a></li></ul>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/605931460/0/petrikainulainen~Introduction-to-Spring-MockMvc/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments></item>
<item>
<feedburner:origLink>https://www.petrikainulainen.net/monthly/software-development-monthly-6-2026/</feedburner:origLink>
		<title>Software Development Monthly 6 / 2026</title>
		<link>https://feeds.feedblitz.com/~/960521540/0/petrikainulainen~Software-Development-Monthly/</link>
					<comments>https://feeds.feedblitz.com/~/960521540/0/petrikainulainen~Software-Development-Monthly/#respond</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Thu, 16 Jul 2026 05:58:37 +0000</pubDate>
				<category><![CDATA[Monthly]]></category>
		<category><![CDATA[Clean Code]]></category>
		<category><![CDATA[Quarkus]]></category>
		<category><![CDATA[Spring AI]]></category>
		<category><![CDATA[Spring Batch]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=29338</guid>
					<description><![CDATA[<p>The Software Development Monthly is a monthly blog post that highlights interesting or useful blog posts which I read during the previous month. This blog post shares 14 interesting or useful blog posts which I read during June 2026. <a rel="NOFOLLOW" class="excerpt_read_more" href="/monthly/software-development-monthly-6-2026/">Read More</a></p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/960521540/0/petrikainulainen~Software-Development-Monthly/">Software Development Monthly 6 / 2026</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/960521540/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/960521540/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/960521540/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/960521540/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p>The Software Development Monthly is a monthly blog post that shares interesting or useful content which I consumed during the previous month. This blog post is always published on the eight day of the month.</p>
<p>Let's begin!</p>
<div class="note">
<strong>Table of Contents:</strong></p>
<ul>
<li><a href="#ai">AI</a></li>
<li><a href="#sw-development">Software Development</a></li>
</ul>
</div>
<h2 id="ai">AI</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://addyosmani.com/blog/loop-engineering/">Loop Engineering</a> provides an introduction to loop engineering where developers design automated feedback loops that programmatically prompt and orchestrate AI agents.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://evilmartians.com/chronicles/ai-assisted-engineers-are-burning-out-is-this-fine">AI-assisted engineers are burning out, is this fine?</a> explains why AI assisted software development can cause burnout and provides five tips that help developers to maintain a sustainable workflow.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://yusufaytas.com/vibe-coder-vs-software-engineer">Vibe Coder vs Software Engineer</a> explains the difference between a vibe coder and a software engineer.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.wheresyoured.at/exclusive-openai-financials/">OpenAI Losses Increased Nearly 8X in 2025</a> reveals that, according to audited financial documents, OpenAI lost $38.5 billion in 2025.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://foojay.io/today/did-ai-just-break-software-security-for-ever/">Did AI Just Break Software Security For Ever?</a> argues that because AI assisted vulnerability research increases the number of vulnerabilities patched in active and well-maintained code bases, the software which uses end-of-life versions becomes exposed to rapid exploitation.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://spring.io/blog/2026/06/15/spring-ai-composable-tool-calling">Tool Calling in Spring AI 2.0: A Composable, Agentic Architecture</a> describes how Spring AI 2.0 improves the tool calling architecture by adding better support for customizing and extending the tool calling loop.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://spring.io/blog/2026/06/23/spring-ai-self-correcting-structured-output">Self-Correcting Structured Output in Spring AI 2.0</a> introduces the improvements to Spring AI's structured output support that were released in Spring AI 2.0.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://foojay.io/today/ai-assisted-unused-dead-code-removal/">Why Your Codebase Is Forcing AI to Underperform, and What to Do About It</a> explains why unused code is a problem and describes how we can safely remove it by using an AI agent to analyze and clean up our code base.</p>
<h2 id="sw-development">Software Development</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://inside.java/2026/06/09/jdk-26-performance-improvements/">Performance Improvements in JDK 26</a> highlights the notable performance improvements introduced in JDK 26.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://foojay.io/today/spring-boot-migration-and-the-cra-when-good-enough-isnt/">Spring Boot Migration and the CRA: When Good Enough Isn’t</a> explains how the upcoming EU Cyber Resilience Act introduces compliance liabilities for organizations running unsupported and vulnerable software.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://foojay.io/today/spring-quarkus-jooby-vertx-java-framework-comparison/">Spring vs Quarkus vs Jooby vs Vert.x: Pick Your Next Java Framework</a> compares four Java frameworks, and identifies the pros and cons of each framework. </p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.sivalabs.in/blog/dont-pollute-spring-boot-main-class/">Don't Pollute Your Spring Boot Main EntryPoint Class</a> explains why it's not a good idea to include "unnecessary" configuration in the Spring Boot's entry point class.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.infoq.com/news/2026/06/spring-boot-4-1/">Spring Boot 4.1 Adds gRPC Auto-Configuration, SSRF Mitigation, and Kotlin 2.3 Support</a> highlights the major improvements introduced in Spring Boot 4.1.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://spring.io/blog/2026/06/21/spring-boot-41-and-spring-batch">MongoDB-backed Spring Batch jobs and more in Spring Boot 4.1</a> describes how we can write Spring Batch jobs which store the metadata in a MongoDB database.</p>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/monthly/software-development-monthly-6-2026/">Software Development Monthly 6 / 2026</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/960521540/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/960521540/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/960521540/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/960521540/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/960521540/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/960521540/0/petrikainulainen~Software-Development-Monthly/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments></item>
<item>
<feedburner:origLink>https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-6-2026/</feedburner:origLink>
		<title>Clean Test Automation Monthly 6 / 2026</title>
		<link>https://feeds.feedblitz.com/~/958878599/0/petrikainulainen~Clean-Test-Automation-Monthly/</link>
					<comments>https://feeds.feedblitz.com/~/958878599/0/petrikainulainen~Clean-Test-Automation-Monthly/#respond</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Thu, 02 Jul 2026 14:29:22 +0000</pubDate>
				<category><![CDATA[Monthly]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[JUnit 5]]></category>
		<category><![CDATA[Playwright]]></category>
		<category><![CDATA[Rest Assured]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=29346</guid>
					<description><![CDATA[<p>The Clean Test Automation Monthly is a monthly blog post that highlights interesting or useful test automation content which I read during the current month. This blog post shares 13 interesting or useful blog posts which I read during June 2026. <a rel="NOFOLLOW" class="excerpt_read_more" href="/monthly/clean-test-automation-monthly-6-2026/">Read More</a></p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/958878599/0/petrikainulainen~Clean-Test-Automation-Monthly/">Clean Test Automation Monthly 6 / 2026</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/958878599/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/958878599/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/958878599/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/958878599/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a><h3 style="clear:left;padding-top:10px">Related Stories</h3><ul><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-6-2025/">Clean Test Automation Monthly 6 / 2025</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-6-2024/">Clean Test Automation Monthly 6 / 2024</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-6-2023/">Clean Test Automation Monthly 6 / 2023</a></li></ul>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p>The Clean Test Automation Monthly is a monthly blog post that shares interesting or useful test automation content which I consumed during the current month. This blog post is always published on the first day of the "next" month.</p>
<p>Let's begin!</p>
<div class="note">
<strong>Table of Contents:</strong></p>
<ul>
<li><a href="#design">Test  Design</a></li>
<li><a href="#backend">Backend</a></li>
<li><a href="#ui-end-to-end">UI / End-to-End</a></li>
</ul>
</div>
<h2 id="design">Test Design</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/06/01/rent-you-dont-need-to-pay/">API Tests – Rent You Don’t Need to Pay</a> defines the term API test, identifies the cost of "duplicate test coverage", and shares practical tips that help us to write good API tests.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://testuff.com/the-ai-testing-hangover-when-more-automation-means-less-confidence/">The AI Testing Hangover: When More Automation Means Less Confidence</a> identifies the cost of valuing quantity over quality, argues that we shouldn't track code coverage, shares four metrics which are more useful, and explains what we should do next.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/06/08/the-layer-you-should-hate-needing/">System/UI Tests – The Layer You Should Hate Needing</a> defines the term system test, identifies bugs that only a system test can catch, and helps us to build a reliable and useful system test suite.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.thegreenreport.blog/articles/the-spec-is-the-contract-how-sdd-is-changing-api-test-strategy/the-spec-is-the-contract-how-sdd-is-changing-api-test-strategy.html">The Spec Is the Contract: How SDD Is Changing API Test Strategy</a> describes how spec-driven development can help us to do contract testing, identifies three risks of spec-driven development, and explains how QA engineers can gain an advantage by co-owning the specification documents.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/06/15/the-conversation-youre-probably-not-having/">The Conversation You’re (Probably) Not Having</a> describes how both QA engineers and developers can increase confidence and reduce production bugs by building healthy collaboration habits.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://testingil.com/2026/06/test-the-feature-not-the-endpoint.html">Test the Feature, Not the Endpoint</a> argues that API tests which test only only one API endpoint don't help us to verify that a feature is working as expected. Thus, if we want to ensure that a feature is working as expected, we should write workflow tests.</p>
<h2 id="backend">Backend</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://foojay.io/today/tiberius-a-security-testing-framework-for-llm-applications-in-java/">Tiberius: A Security Testing Framework for LLM Applications in Java</a> provides a quick introduction to Tiberius which is a vulnerability and security testing library that integrates with both JUnit Jupiter and Spring Boot.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://medium.com/javarevisited/rest-assured-configuration-and-specifications-writing-maintainable-api-tests-cfadda5fa671">Rest-Assured Configuration and Specifications: Writing Maintainable API Tests</a> demonstrates how we can remove duplicate code from our API tests which use Rest Assured.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://blog.johanneslink.net/2026/06/09/the-jqwik-anti-ai-affair/">The Jqwik Anti-AI Affair</a> explains why the author of the Jqwik library decided to add the "infamous line" to the standard output of each test run.</p>
<h2 id="ui-end-to-end">UI / End-to-End</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://amitrawat.dev/blog/three-paths-to-agentic-ui-automation">Three Paths to Agentic UI Automation</a> identifies three different approaches which an AI agent can use when it wants to drive a browser, explains the pros and cons of each approach, and helps us to select the correct approach.</p>
<p>Data Driven API Testing in Playwright TypeScript: <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://levelup.gitconnected.com/data-driven-api-testing-in-playwright-typescript-part-1-cc4f7deaf74a">Part 1</a> and <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://levelup.gitconnected.com/data-driven-api-testing-in-playwright-typescript-part-2-5d6e84f5da45">Part 2</a> is a two part tutorial that provides a quick introduction to data-driven testing and explains how we can write data-driven API tests with Typescript and Playwright.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://dev.to/playwright/mocking-server-side-http-in-playwright-with-mockttp-58jo">Mocking Server Side HTTP in Playwright with mockttp </a> describes how we can write Playwright tests which mock HTTP requests with mockttp.</p>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-6-2026/">Clean Test Automation Monthly 6 / 2026</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/958878599/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/958878599/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/958878599/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/958878599/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/958878599/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a><h3 style="clear:left;padding-top:10px">Related Stories</h3><ul><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-6-2025/">Clean Test Automation Monthly 6 / 2025</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-6-2024/">Clean Test Automation Monthly 6 / 2024</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-6-2023/">Clean Test Automation Monthly 6 / 2023</a></li></ul>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/958878599/0/petrikainulainen~Clean-Test-Automation-Monthly/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments></item>
<item>
<feedburner:origLink>https://www.petrikainulainen.net/monthly/software-development-monthly-5-2026/</feedburner:origLink>
		<title>Software Development Monthly 5 / 2026</title>
		<link>https://feeds.feedblitz.com/~/958063919/0/petrikainulainen~Software-Development-Monthly/</link>
					<comments>https://feeds.feedblitz.com/~/958063919/0/petrikainulainen~Software-Development-Monthly/#respond</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Mon, 15 Jun 2026 16:59:50 +0000</pubDate>
				<category><![CDATA[Monthly]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[ArchUnit]]></category>
		<category><![CDATA[jOOQ]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=29301</guid>
					<description><![CDATA[<p>The Software Development Monthly is a monthly blog post that highlights interesting or useful blog posts which I read during the previous month. This blog post shares 19 interesting or useful blog posts which I read during May 2026. <a rel="NOFOLLOW" class="excerpt_read_more" href="/monthly/software-development-monthly-5-2026/">Read More</a></p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/958063919/0/petrikainulainen~Software-Development-Monthly/">Software Development Monthly 5 / 2026</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/958063919/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/958063919/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/958063919/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/958063919/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p>The Software Development Monthly is a monthly blog post that shares interesting or useful content which I consumed during the previous month. This blog post is always published on the eight day of the month.</p>
<p>Let's begin!</p>
<div class="note">
<strong>Table of Contents:</strong></p>
<ul>
<li><a href="#ai">AI</a></li>
<li><a href="#sw-development">Software Development</a></li>
</ul>
</div>
<h2 id="ai">AI</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://nooneshappy.com/article/appearing-productive-in-the-workplace/">Appearing Productive in The Workplace</a> argues that generative AI enables employees to impersonate expertise and helps to create a false sense of productivity.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://00f.net/2026/05/17/developping-in-the-open/">Bun's problem may be developing in the open</a> explains how public and transparent development can backfire if users mistake experiments for code that will be actually released.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.wheresyoured.at/ai-is-too-expensive/">AI Is Too Expensive</a> argues that the only companies which can make money from generative AI are construction companies, NVIDIA, and hardware manufacturers. </p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://isaiprofitable.com/">Is AI Profitable Yet?</a> tracks the gap between costs and revenue of AI companies (in "real" time).</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://geohot.github.io/blog/jekyll/update/2026/05/24/the-eternal-sloptember.html">The Eternal Sloptember</a> explains that adopting AI agents is a costly mistake, especially for large organizations, because the bottom performers generate ten times more code without understanding the generated code.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://thoughts.hmmz.org/2026-05-31.html">The solution might be cancelling my AI subscription</a> argues that because AI tools have made it so easy to generate code, the author has wasted time generating multiple side projects he has no hope or interest in maintaining.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://pivot-to-ai.com/2026/05/29/test-software-tells-code-bots-delete-me-ai-bros-outraged/">Test software tells code bots ‘delete me’ — AI bros outraged</a> reports an incident where a jqwik maintainer added a log message which asked AI agents to delete all jqwik tests and code.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://martinelli.ch/ai-writes-code-engineers-build-software/">AI Writes Code. Engineers Build Software</a> argues that even though AI is very good at generating code, it cannot do software engineering such as architecture design or requirements gathering.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://blog.frankel.ch/tokensparsamkeit-coding-assistants/">Tokensparsamkeit for coding assistants</a> explores methods for minimizing token consumption when we are using AI coding assistants.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://martinfowler.com/articles/sensors-for-coding-agents.html">Maintainability sensors for coding agents</a> explores different tools we can use for guiding the AI agents to write more maintainable code.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://henrikwarne.com/2026/05/31/with-claude-less-coding-more-testing/">With Claude: Less Coding, More Testing</a> explains that using AI for generating code shifts the developer's primary role from writing code to verifying the output.</p>
<h2 id="sw-development">Software Development</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://howtocenterdiv.com/beyond-the-div/nobody-pushed-back">Nobody Pushed Back: Why Engineers Stay Silent Until It's Too Late</a> explains that if the company culture punishes people who speak up, people often choose safety over being right.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://fbritoferreira.com/blog/no-juniors-today-no-seniors-in-2031/">No Juniors Today, No Seniors in 2031</a> argues that if companies won't hire and mentor junior developers, they will face a critical shortage of senior engineers in 2031.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://daniel.haxx.se/blog/2026/05/26/the-pressure/">The pressure</a> explains that the curl developers are facing a lot of pressure due to the massive influx of high-quality vulnerability reports and highlights a fundamental problem faced by even the most popular open source projects: lack of funding. </p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://fagnerbrack.com/learn-sql-once-use-it-for-30-years-9aceb0bdee03">Learn SQL Once, Use It for 30 Years</a> argues that because SQL is built on mathematical principles and not on shifting industry trends, we can learn it once and use it without the need to update our mental model.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://blog.jooq.org/why-join-using-can-lead-to-errors-in-sql/">Why JOIN USING Can Lead to Errors in SQL</a> argues that even though <code>JOIN USING</code> is useful in ad-hoc queries, we shouldn't use it in production code because adding new columns to a database table can break existing queries which use the <code>JOIN USING</code> syntax.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://blog.jooq.org/simplifying-anti-join-with-jooq-syntax/">Simplifying ANTI JOIN with jOOQ Syntax</a> introduces different options for writing anti join queries with jOOQ.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://martinfowler.com/articles/what-is-code.html">What Is Code?</a> argues that because AI makes code generation easier, we should concentrate on discovering the right vocabulary and building precise conceptual models. </p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://netflixtechblog.com/scaling-archunit-with-nebula-archrules-b4642c464c5a">Scaling ArchUnit with Nebula ArchRules</a> describes how Netflix leverages ArchUnit for tracking quality issues across over 5000 repositories.</p>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/monthly/software-development-monthly-5-2026/">Software Development Monthly 5 / 2026</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/958063919/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/958063919/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/958063919/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/958063919/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/958063919/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/958063919/0/petrikainulainen~Software-Development-Monthly/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments></item>
<item>
<feedburner:origLink>https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-5-2026/</feedburner:origLink>
		<title>Clean Test Automation Monthly 5 / 2026</title>
		<link>https://feeds.feedblitz.com/~/957616745/0/petrikainulainen~Clean-Test-Automation-Monthly/</link>
					<comments>https://feeds.feedblitz.com/~/957616745/0/petrikainulainen~Clean-Test-Automation-Monthly/#respond</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Mon, 01 Jun 2026 15:11:31 +0000</pubDate>
				<category><![CDATA[Monthly]]></category>
		<category><![CDATA[Clean Tests]]></category>
		<category><![CDATA[Gradle]]></category>
		<category><![CDATA[JUnit 5]]></category>
		<category><![CDATA[MockK]]></category>
		<category><![CDATA[Playwright]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=29266</guid>
					<description><![CDATA[<p>The Clean Test Automation Monthly is a monthly blog post that highlights interesting or useful test automation content which I read during the current month. This blog post shares 14 interesting or useful blog posts which I read during May 2026. <a rel="NOFOLLOW" class="excerpt_read_more" href="/monthly/clean-test-automation-monthly-5-2026/">Read More</a></p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/957616745/0/petrikainulainen~Clean-Test-Automation-Monthly/">Clean Test Automation Monthly 5 / 2026</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/957616745/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/957616745/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/957616745/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/957616745/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a><h3 style="clear:left;padding-top:10px">Related Stories</h3><ul><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-5-2025/">Clean Test Automation Monthly 5 / 2025</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-5-2024/">Clean Test Automation Monthly 5 / 2024</a></li></ul>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p>The Clean Test Automation Monthly is a monthly blog post that shares interesting or useful test automation content which I consumed during the current month. This blog post is always published on the first day of the "next" month.</p>
<p>Let's begin!</p>
<div class="note">
<strong>Table of Contents:</strong></p>
<ul>
<li><a href="#design">Test  Design</a></li>
<li><a href="#backend">Backend</a></li>
<li><a href="#ui-end-to-end">UI / End-to-End</a></li>
</ul>
</div>
<h2 id="design">Test Design</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/04/27/the-flaky-tests-truce/">The Flaky Tests Truce</a> argues that sometimes we should retry a failed test and provides five tips that help us to write tests that serve the product. </p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://medium.com/@fernanda.nadhiftya/why-f-i-r-s-t-testing-still-wins-after-20-years-92cc28e21d69">Why F.I.R.S.T. Testing Still Wins After 20 Years</a> explains why we should write tests which are fast, isolated, repeatable, self-validating, and timely.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/05/09/most-test-frameworks-are-overengineered/">Most Test Frameworks Are Over-Engineered</a> identifies the hidden costs of an elegant in-house testing framework and provides four questions that help us decide whether our own test framework is a solution or a problem.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/05/11/test-pyramid-isnt-dead/">The Pyramid Isn’t Dead, You’re Just Not Using It Right</a> is the first part of the "The Test Pyramid — Reimagined" series, and it argues that a test pyramid is still a useful tool for making tradeoffs between the number of different (unit, integration, API, and system) tests, the duration of our test run, and maintenance costs. Remember to check out the next parts of the series: <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/05/14/unit-tests-your-codes-loudest-critic/">Unit Tests – Your Code’s Loudest Critic</a>, <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/05/18/integraton-tests-reclaiming-the-middle/">Integration Tests – Reclaiming the Middle</a>, and <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/05/25/the-line-you-forgot-to-draw/">The Line You Forgot to Draw</a>.</p>
<h2 id="backend">Backend</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.baeldung.com/junit5-gradle-parallel-testing">Parallel Testing With Gradle and JUnit 5</a> describes how we can run our tests in parallel with Gradle when we using JUnit Jupiter, and identifies two issues that can cause problems for parallel test runs and explains how we can solve them.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/programming/unit-testing/getting-started-with-mockk-the-setup/">Getting Started With MockK: The Setup</a> describes how we can get the required dependencies with Maven and Gradle, and configure the system under test by using both manual and extension-based configuration.</p>
<h2 id="ui-end-to-end">UI / End-to-End</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://goforthandtest.com/2026/04/25/confessions-of-a-recovering-selenium-developer/">Confessions of a Recovering Selenium Developer</a> explains why the author stopped using Selenium and replaced it with Playwright.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://medium.com/@slavik.pashanin/intercept-everything-api-logging-middleware-for-playwright-bfb67ef54be3">Intercept Everything: API Logging Middleware for Playwright</a> describes how we can implement a component that includes both the HTTP request and response in the HTML report generated by Playwright.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.davidmello.com/software-testing/test-automation/what-would-you-stop-doing-when-ui-tests-are-flaky">What Would You Stop Doing When UI Tests Are Flaky?</a> explores this QA interview question and identifies the common (wrong) answers, explains why candidates are answering to the wrong question, and describes how the author would answer to this question.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://scrolltest.com/playwright-sharding-docker-cut-test-time/">Playwright Sharding and Docker: How I Cut My Test Suite from 47 Minutes to 8 Minutes</a> explains why something had to be done and describes how the author cut 39 minutes from the run time of their Playwright regression test suite by using Playwright sharding, Docker, and Github Actions.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.thegreenreport.blog/articles/when-offline-isnt-enough-adding-network-throttling-to-playwright/when-offline-isnt-enough-adding-network-throttling-to-playwright.html">When Offline Isn't Enough: Adding Network Throttling to Playwright</a> explains how we can simulate network constraints such as high latency and restricted upload or download speeds with Playwright.</p>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-5-2026/">Clean Test Automation Monthly 5 / 2026</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/957616745/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/957616745/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/957616745/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/957616745/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/957616745/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a><h3 style="clear:left;padding-top:10px">Related Stories</h3><ul><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-5-2025/">Clean Test Automation Monthly 5 / 2025</a></li><li><a rel="NOFOLLOW" href="https://www.petrikainulainen.net/monthly/clean-test-automation-monthly-5-2024/">Clean Test Automation Monthly 5 / 2024</a></li></ul>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/957616745/0/petrikainulainen~Clean-Test-Automation-Monthly/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments></item>
<item>
<feedburner:origLink>https://www.petrikainulainen.net/programming/unit-testing/getting-started-with-mockk-the-setup/</feedburner:origLink>
		<title>Getting Started With MockK: The Setup</title>
		<link>https://feeds.feedblitz.com/~/956061056/0/petrikainulainen~Getting-Started-With-MockK-The-Setup/</link>
					<comments>https://feeds.feedblitz.com/~/956061056/0/petrikainulainen~Getting-Started-With-MockK-The-Setup/#respond</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Fri, 15 May 2026 09:40:39 +0000</pubDate>
				<category><![CDATA[Unit Testing]]></category>
		<category><![CDATA[JUnit 5]]></category>
		<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[MockK]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=28820</guid>
					<description><![CDATA[<p>This blog post describes how we can configure the system under test and replace its dependencies with mocks when we are writing unit tests for a Kotlin application by using JUnit Jupiter and MockK. We will learn to get the required dependencies and configure the system under test by using both manual and extension-based configuration. <a rel="NOFOLLOW" class="excerpt_read_more" href="/programming/unit-testing/getting-started-with-mockk-the-setup/">Read More</a></p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/956061056/0/petrikainulainen~Getting-Started-With-MockK-The-Setup/">Getting Started With MockK: The Setup</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/956061056/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/956061056/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/956061056/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/956061056/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://mockk.io/">MockK</a> is a mocking library which embraces Kotlin's unique features such as "final by default", objects, and coroutines. That's why we should use it if we have to write unit tests for a Kotlin project. In this first part of my MockK tutorial, we will learn how to create mocks with MockK and JUnit Jupiter.</p>
<p>After we have finished this blog post, we:</p>
<ul>
<li>Can get the required dependencies with Maven and Gradle.</li>
<li>Understand how we can create mocks with MockK.</li>
</ul>
<p>Let's begin.</p>
<div class="note"><strong>This blog post assumes that:</strong></p>
<ul>
<li>You know how you can create a Kotlin project with <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://kotlinlang.org/docs/gradle.html">Gradle</a> or <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://kotlinlang.org/docs/maven.html">Maven</a>.</li>
<li>You are familiar with JUnit Jupiter.</li>
</ul>
</div>
<h2>Getting the Required Dependencies</h2>
<p>Before we can write tests which use MockK, we have to choose between the standard MockK API and its BDD (Behavior-Driven Development) variant. Basically, we have to choose between the classic <code>every</code>/<code>verify</code> syntax and the BDD style <code>given</code>/<code>then</code> syntax. This choice defines the MockK module which we must add to the classpath.</p>
<p>The following table identifies the different modules provided by MockK:</p>
<table class="compare-table">
<tr>
<th>Build Tool</th>
<th>Test Style</th>
<th>Group ID</th>
<th>Artifact ID</th>
<th>Configuration / Scope</th>
</tr>
<tr>
<td>Gradle</td>
<td>Standard</td>
<td><code>io.mockk</code></td>
<td><code>mockk</code></td>
<td><code>testImplementation</code></td>
</tr>
<tr>
<td>Gradle</td>
<td>BDD</td>
<td><code>io.mockk</code></td>
<td><code>mockk-bdd</code></td>
<td><code>testImplementation</code></td>
</tr>
<tr>
<td>Maven</td>
<td>Standard</td>
<td><code>io.mockk</code></td>
<td><code>mockk-jvm</code></td>
<td><code>test</code></td>
</tr>
<tr>
<td>Maven</td>
<td>BDD</td>
<td><code>io.mockk</code></td>
<td><code>mockk-bdd-jvm</code></td>
<td><code>test</code></td>
</tr>
</table>
<p><strong>Example 1: Gradle</strong></p>
<p>If we want to use the standard MockK API with Gradle, we have to add the <code>mockk</code> dependency (version 1.14.9) to the <code>testImplementation</code> dependency configuration. We can do this by adding the following line to the <code>dependencies</code> block of our <em>build.gradle.kts</em> file:</p>
<pre class="brush: java; title: ; notranslate">
testImplementation(&quot;io.mockk:mockk:1.14.9&quot;)
</pre>
<p><strong>Example 2: Maven</strong></p>
<p>If we want to use the standard MockK API with Maven, we have to add the <code>mockk-jvm</code> dependency (version 1.14.9) to the <code>test</code> scope. We can do this by adding the following dependency declaration to the <code>dependencies</code> section of our <em>pom.xml</em> file:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;dependency&gt;
    &lt;groupId&gt;io.mockk&lt;/groupId&gt;
    &lt;artifactId&gt;mockk-jvm&lt;/artifactId&gt;
    &lt;version&gt;1.14.9&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
</pre>
<div class="note">We must use different artifact IDs for Gradle and Maven because:</p>
<ul>
<li>MockK is a <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://kotlinlang.org/docs/multiplatform/get-started.html">Kotlin Multiplatform</a> project that's published with <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.gradle.org/current/userguide/publishing_gradle_module_metadata.html">Gradle module metadata</a>.</li>
<li>Because Gradle can read its own module metadata, it can resolve the correct variant automatically.</li>
<li>Because Maven cannot read Gradle's module metadata, we have to explicitly specify the variant we want to use.</li>
</ul>
</div>
<p>Next, we will take a closer look at the system under test.</p>
<h2>Introduction to the System Under Test</h2>
<p>During this blog post we will start writing tests for a component which allows us to register new user accounts. The implementation of this component is described in the following:</p>
<p>The <code>User.kt</code> file contains two data classes and one exception. These classes are:</p>
<ul>
<li>The <code>RegisterUserAccountRequest</code> class contains the information that's used to register a new user account.</li>
<li>The <code>UserAccount</code> class contains the information of a user account that's found from the database.</li>
<li>The <code>UserAccountExistsException</code> is a runtime exception that's thrown if the registered user account doesn't have a unique email address.</li>
</ul>
<p>The source code of the <code>User.kt</code> file looks as follows:</p>
<pre class="brush: java; title: ; notranslate">
data class RegisterUserAccountRequest(val email: String, val name: String)
data class UserAccount(val id: Long, val email: String, val name: String)
class UserAccountExistsException(email: String) :
    RuntimeException(&quot;The user account with email address: $email exists&quot;)
</pre>
<p>The <code>UserRepository</code> interface declares two functions:</p>
<ul>
<li>The <code>existsByEmail()</code> function returns <code>true</code> if the email address given as an argument is used by an existing user account and <code>false</code> otherwise.</li>
<li>The <code>save()</code> function saves the user account provided as an argument and returns the information that's inserted into the database.</li>
</ul>
<p>The source code of the <code>UserRepository</code> interface looks as follows:</p>
<pre class="brush: java; title: ; notranslate">
interface UserRepository {
    fun existsByEmail(email: String): Boolean
    fun save(input: RegisterUserAccountRequest): UserAccount
}
</pre>
<p>The <code>EmailService</code> interface declares one function that's used to send a welcome email to a new user after their user account has been registered. The source code of the <code>EmailService</code> interface looks as follows:</p>
<pre class="brush: java; title: ; notranslate">
interface EmailService {
    fun sendWelcomeEmail(email: String)
}
</pre>
<p>The <code>UserAccountRegistrationService</code> class has one function called <code>registerUserAccount()</code> that's implemented by following these steps:</p>
<ol>
<li>Throw the <code>UserAccountExistsException</code> if the registered user account doesn't have a unique email address.</li>
<li>Insert a new user account into the database.</li>
<li>Send the welcome email to the user.</li>
<li>Return the information that was inserted into the database.</li>
</ol>
<p>The source code of the <code>UserAccountRegistrationService</code> class looks as follows:</p>
<pre class="brush: java; title: ; notranslate">
class UserAccountRegistrationService(
    private val repository: UserRepository,
    private val emailService: EmailService
) {
    fun registerUserAccount(input: RegisterUserAccountRequest): UserAccount {
        if (repository.existsByEmail(input.email)) {
            throw UserAccountExistsException(input.email)
        }
        val registeredUserAccount = repository.save(input)
        emailService.sendWelcomeEmail(registeredUserAccount.email)
        return registeredUserAccount
    }
}
</pre>
<p>Let's move on and find out how we can create mocks with MockK and configure the system under test with JUnit Jupiter.</p>
<h2>Creating Mocks With MockK</h2>
<p>When we are writing our tests with JUnit Jupiter and we want to create mocks with MockK, we have two viable options:</p>
<ul>
<li>We can create a mock manually by invoking the <code>mockk()</code> function.</li>
<li>We can use the <code>MockKExtension</code> together with the <code>@MockK</code> and <code>@InjectMockKs</code> annotations.</li>
</ul>
<p>Let's start and find out how we can create mocks manually by using the <code>@BeforeEach</code> function.</p>
<h3>Creating Mocks Manually by Using the @BeforeEach Function</h3>
<p>When we want to replace the <code>UserRepository</code> and the <code>EmailService</code> dependencies of the <code>UserAccountRegistrationService</code> class with mocks by using the <code>@BeforeEach</code> function, we have to follow these steps:</p>
<p><strong>1.</strong> Create a new test class and add three <code>private lateinit</code> properties to the created test class:</p>
<ul>
<li>The <code>repository</code> property contains the <code>UserRepository</code> mock.</li>
<li>The <code>emailService</code> property contains the <code>EmailService</code> mock.</li>
<li>The <code>service</code> property contains the system under test (a <code>UserAccountRegistrationService</code> object).</li>
</ul>
<p>After we have added these properties to our test class, its source code looks as follows:</p>
<pre class="brush: java; highlight: [3,4,5]; title: ; notranslate">
class UserAccountRegistrationServiceManualTest {
    private lateinit var repository: UserRepository
    private lateinit var emailService: EmailService
    private lateinit var service: UserAccountRegistrationService
}
</pre>
<p><strong>2.</strong> Add a setup function to our test class and ensure that this function is invoked before a test function is run. After we have added a new setup function to our test class, its source code looks as follows:</p>
<pre class="brush: java; highlight: [9,10,11,12]; title: ; notranslate">
import org.junit.jupiter.api.BeforeEach
class UserAccountRegistrationServiceManualTest {
    private lateinit var repository: UserRepository
    private lateinit var emailService: EmailService
    private lateinit var service: UserAccountRegistrationService
    @BeforeEach
    fun configureSystemUnderTest() {
    }
}
</pre>
<p><strong>3.</strong> Implement the setup function by following these steps:</p>
<ol>
<li>Create new <code>UserRepository</code> and <code>EmailService</code> mocks by invoking the <code>mockk()</code> function and store the created mocks in the <code>repository</code> and <code>emailService</code> properties.</li>
<li>Create a new <code>UserAccountRegistrationService</code> object and store the created object in the <code>service</code> property.</li>
</ol>
<p>After we have implemented the setup function, the source code of our test class looks as follows:</p>
<pre class="brush: java; highlight: [12,13,14]; title: ; notranslate">
import io.mockk.mockk
import org.junit.jupiter.api.BeforeEach
class UserAccountRegistrationServiceManualTest {
    private lateinit var repository: UserRepository
    private lateinit var emailService: EmailService
    private lateinit var service: UserAccountRegistrationService
    @BeforeEach
    fun configureSystemUnderTest() {
        repository = mockk()
        emailService = mockk()
        service = UserAccountRegistrationService(repository, emailService)
    }
}
</pre>
<p>We have now configured the system under test by using the <code>@BeforeEach</code> function. Let's take a look at the pros and cons of this approach:</p>
<p><strong>Pros:</strong></p>
<ul>
<li><strong>Tests are isolated</strong>. Because every test function gets new mocks and a new system under test, there is no risk of "configuration leakage". In other words, stubbed functions and verifications cannot leak from one test to another.</li>
<li><strong>Doesn't require a specific test instance lifecycle mode</strong>. If we create the required mocks and the system under test in the <code>@BeforeEach</code> function, our test functions are isolated in every supported test instance lifecycle mode of JUnit Jupiter. For example, because we create new objects and assign property values before every test function, our configuration guarantees a clean slate even if JUnit Jupiter is reusing the test class instance.</li>
<li><strong>Explicit dependency injection</strong>. Because we create the system under test manually in the <code>@BeforeEach</code> function, we don't have to worry about the reflection magic that's used if we configure the system under test by using annotations.</li>
<li><strong>Can be used as a design tool</strong>. Because we have to manually create the system under test, we will feel the pain immediately if the system under test has too many dependencies. If it feels cumbersome to write the code that configures the system under test or the constructor call becomes so long that it's hard to read, we should refactor the system under test.</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><strong>Requires nullable or lateinit properties</strong>. Because the properties are initialized in a <code>@BeforeEach</code> function and not in a test class constructor, we are forced to use nullable types or lateinit properties. This is a problem because:
<ul>
<li>If we use a lateinit property: we must use <code>var</code> instead of <code>val</code> and we cannot rely on compile-time null safety. In other words, the property can be accidentally reassigned outside of the <code>@BeforeEach</code> function, or we might simply forget to assign its value. The problem is that instead of a compiler error, we get a runtime error during test execution.</li>
<li>If we use a nullable type: we have to pay the "null-safety" tax (either use the "bang-bang" operator (<code>!!</code>) or do safe calls (<code>?.</code>)), we have to provide a default value (<code>null</code>) that's immediately replaced either with a mock or the tested object, and we mask the intent of the property because in Kotlin a nullable type typically means that the value can be missing which isn't the case here.</li>
</ul>
</li>
<li><strong>Requires boilerplate code</strong>. We have to write the setup code manually for every test class. This means that our test suite will have setup code that isn't, strictly speaking, required.</li>
<li><strong>Requires maintenance</strong>. If we add a new dependency to the system under test, we have to add a new lateinit property to our test class, create a new mock object in the <code>@BeforeEach</code> function, and modify the constructor call which creates the tested object.</li>
</ul>
<div class="note"><strong>Additional Reading:</strong></p>
<ul>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.junit.org/6.0.3/writing-tests/test-classes-and-methods.html">JUnit User Guide: Test Classes and Methods</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.junit.org/6.0.3/writing-tests/test-instance-lifecycle.html">JUnit User Guide: Test Instance Lifecycle</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.junit.org/6.0.3/api/org.junit.jupiter.api/org/junit/jupiter/api/BeforeEach.html">The Javadoc of the <code>@BeforeEach</code> annotation</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://kotlinlang.org/docs/properties.html">Kotlin Language Guide: Properties</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://kotlinlang.org/docs/null-safety.html">Kotlin Language Guide: Null Safety</a></li>
</ul>
</div>
<p>Next, we will find how we can create mocks manually as immutable class properties.</p>
<h3>Creating Mocks Manually as Immutable Class Properties</h3>
<p>When we want to replace the <code>UserRepository</code> and the <code>EmailService</code> dependencies of the <code>UserAccountRegistrationService</code> class with mocks, and add these mocks and the system under test to our test class as immutable class properties, we have to create a new test class and follow these steps:</p>
<ol>
<li>Add a <code>private</code> and immutable <code>repository</code> property to our test class and ensure that it contains a <code>UserRepository</code> mock.</li>
<li>Add a <code>private</code> and immutable <code>emailService</code> property to our test class and ensure that it contains an <code>EmailService</code> mock.</li>
<li>Add a <code>private</code> and immutable <code>service</code> property to our test class and ensure that it contains a new <code>UserAccountRegistrationService</code> object. Remember to pass the <code>UserRepository</code> and the <code>EmailService</code> mocks as constructor arguments.</li>
</ol>
<p>After we have added the immutable class properties to our test class, its source code looks as follows:</p>
<pre class="brush: java; highlight: [5,6,7]; title: ; notranslate">
import io.mockk.mockk
class UserAccountRegistrationServiceManualClassPropertyTest {
    private val repository = mockk&lt;UserRepository&gt;()
    private val emailService = mockk&lt;EmailService&gt;()
    private val service = UserAccountRegistrationService(repository, emailService)
}
</pre>
<p>We have now configured the system under test by using immutable class properties. Let's take a look at the pros and cons of this approach.</p>
<p><strong>Pros:</strong></p>
<ul>
<li><strong>All class properties are immutable</strong>. They cannot be reassigned and they cannot be <code>null</code>.</li>
<li><strong>Tests are isolated (if we use the correct test instance lifecycle mode)</strong>. Because every test function gets new mocks and a new system under test, there is no risk of "configuration leakage". In other words, stubbed functions and verifications cannot leak from one test to another.</li>
<li><strong>Explicit dependency injection</strong>. Because we create the system under test manually, we don't have to worry about the reflection magic that's used if we configure the system under test by using annotations.</li>
<li><strong>Can be used as a design tool</strong>. Because we have to manually create the system under test, we will feel the pain immediately if the system under test has too many dependencies. If it feels cumbersome to write the code configures the system under test or the constructor call becomes so long that it's hard to read, we should refactor the system under test.</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><strong>JUnit Jupiter must create a new test instance for every test function</strong> (this is the default behavior). As long as JUnit Jupiter creates a new test instance for every test function, there is no risk of "configuration leakage". If the JUnit Jupiter is configured the create a new test instance once per test class, a test function will inherit the stubs and recorded interactions from the previous test function (if we don't do manual cleanup). This shared state can lead to flaky tests where the outcome of one test depends on the execution order of the other tests.</li>
<li><strong>Requires boilerplate code</strong>. We have to write the setup code manually for every test class. This means that our test suite will have setup code that isn't, strictly speaking, required.</li>
<li><strong>Requires maintenance</strong>. If we add a new dependency to the system under test, we have to add a new immutable class property to our test class, create a new mock object, and modify the constructor call which creates the tested object.</li>
</ul>
<div class="note"><strong>Additional Reading:</strong></p>
<ul>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.junit.org/6.0.3/writing-tests/test-instance-lifecycle.html">JUnit User Guide: Test Instance Lifecycle</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://kotlinlang.org/docs/properties.html">Kotlin Language Guide: Properties</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://kotlinlang.org/docs/null-safety.html">Kotlin Language Guide: Null Safety</a></li>
</ul>
</div>
<p>Let's move on and find out how we can create mocks by using the JUnit Jupiter extension together with the <code>@MockK</code> and <code>@InjectMockKs</code> annotations.</p>
<h3>Using the JUnit Jupiter Extension</h3>
<p>When we want to replace the <code>UserRepository</code> and the <code>EmailService</code> dependencies of the <code>UserAccountRegistrationService</code> class with mocks by using MockK JUnit Jupiter extension, we have to follow these steps:</p>
<p><strong>1.</strong> Create a new test class and add three <code>private lateinit</code> properties to the created test class:</p>
<ul>
<li>The <code>repository</code> property contains the <code>UserRepository</code> mock.</li>
<li>The <code>emailService</code> property contains the <code>EmailService</code> mock.</li>
<li>The <code>service</code> property contains the system under test (a <code>UserAccountRegistrationService</code> object).</li>
</ul>
<p>After we have added these properties to our test class, its source code looks as follows:</p>
<pre class="brush: java; highlight: [3,4,5]; title: ; notranslate">
class UserAccountRegistrationServiceExtensionTest {
    private lateinit var repository: UserRepository
    private lateinit var emailService: EmailService
    private lateinit var service: UserAccountRegistrationService
}
</pre>
<p><strong>2.</strong> Annotate the <code>repository</code> and <code>emailService</code> properties with the <code>@MockK</code> annotation. This annotation identifies the properties that contain mocks and instructs the MockK JUnit Jupiter extension to create the required mock objects. After we have annotated these properties with the <code>@MockK</code> annotation, the source code of our test class looks as follows:</p>
<pre class="brush: java; highlight: [5,6,7,8,9]; title: ; notranslate">
import io.mockk.impl.annotations.MockK
class UserAccountRegistrationServiceExtensionTest {
    @MockK
    private lateinit var repository: UserRepository
    @MockK
    private lateinit var emailService: EmailService
    private lateinit var service: UserAccountRegistrationService
}
</pre>
<p><strong>3.</strong> Annotate the <code>service</code> property with the <code>@InjectMockKs</code> annotation. This annotation identifies the property initialized by the MockK JUnit Jupiter extension and instructs it to replace the dependencies of the created object with mocks. After we have done this, the source code of our test class looks as follows:</p>
<pre class="brush: java; highlight: [12]; title: ; notranslate">
import io.mockk.impl.annotations.InjectMockKs
import io.mockk.impl.annotations.MockK
class UserAccountRegistrationServiceExtensionTest {
    @MockK
    private lateinit var repository: UserRepository
    @MockK
    private lateinit var emailService: EmailService
    @InjectMockKs
    private lateinit var service: UserAccountRegistrationService
}
</pre>
<p><strong>4.</strong> Register the used JUnit Jupiter extension by annotating our test class with the <code>@ExtendWith</code> annotation. After we have registered the <code>MockKExtension</code>, the source code of our test class looks as follows:</p>
<pre class="brush: java; highlight: [6]; title: ; notranslate">
import io.mockk.impl.annotations.InjectMockKs
import io.mockk.impl.annotations.MockK
import io.mockk.junit5.MockKExtension
import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(MockKExtension::class)
class UserAccountRegistrationServiceExtensionTest {
    @MockK
    private lateinit var repository: UserRepository
    @MockK
    private lateinit var emailService: EmailService
    @InjectMockKs
    private lateinit var service: UserAccountRegistrationService
}
</pre>
<p>We have now configured the system under test by using the MockK JUnit Jupiter extension. Let's take a look at the pros and cons of this approach:</p>
<p><strong>Pros:</strong></p>
<ul>
<li><strong>Tests are isolated</strong>. The MockK JUnit Jupiter extension ensures that every test function gets clean mocks. In other words, it makes sure that stubbed functions and verifications cannot leak from one test to another.</li>
<li><strong>Minimal Boilerplate</strong>. We don't have to manually invoke the <code>mockk()</code> function or invoke the constructor of the tested class. We can simply describe what we want by using the <code>@MockK</code> and <code>@InjectMockKs</code> annotations, and the MockK JUnit Jupiter extension will do the hard lifting for us.</li>
<li><strong>Clean Class Structure</strong>. Because the MockK JUnit Jupiter extension creates the mock objects and the tested object, our test class looks clean. All properties are listed at the top of the test class, and the <code>@MockK</code> and <code>@InjectMockKs</code> annotations make it clear what's mocked and what's tested.</li>
</ul>
<p><strong>Cons:</strong></p>
<ul>
<li><strong>Requires nullable or lateinit properties</strong>. Because the test class properties are initialized by the MockK JUnit Jupiter extension after the test class is instantiated (and not in a test class constructor), we are forced to use nullable types or lateinit properties. This is a problem because:
<ul>
<li>If we use a lateinit property: we must use <code>var</code> instead of <code>val</code> and we cannot rely on compile-time null safety. In other words, the property can be accidentally reassigned, or we might simply forget to assign its value. The problem is that instead of a compiler error, we get a runtime error during test execution.</li>
<li>If we use a nullable type: we have to pay the "null-safety" tax (either use the "bang-bang" operator (<code>!!</code>) or do safe calls (<code>?.</code>)), we have to provide a default value (<code>null</code>) that's immediately replaced either with a mock or the tested object, and we mask the intent of the property because in Kotlin a nullable type typically means that the value can be missing which isn't the case here.</li>
</ul>
</li>
<li><strong>Hides bad design</strong>. Because it's so easy to create a new mock and inject it into the system under test, we might not realize that the system under test has too many dependencies until it's too late. In other words, we don't feel the "constructor friction" that acts as a design tool.</li>
<li><strong>Relies on reflection and "magic"</strong>. The MockK JUnit Jupiter extension relies heavily on reflection. This leads into a "magic" behavior that's harder to debug than plain Kotlin code. Also, if something goes wrong, it's likely that we will get a confusing error message at runtime instead of a clean compilation error.</li>
</ul>
<div class="note"><strong>Additional Reading:</strong></p>
<ul>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://docs.junit.org/6.0.3/extensions/registering-extensions.html">JUnit User Guide: Registering Extensions</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://mockk.io/#junit5">MockK User Guide: JUnit 5</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://kotlinlang.org/docs/properties.html">Kotlin Language Guide: Properties</a></li>
<li><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://kotlinlang.org/docs/null-safety.html">Kotlin Language Guide: Null Safety</a></li>
</ul>
</div>
<p>We can now get the required dependencies with Maven and Gradle, and we understand how we can create mocks with MockK. Let's summarize what we learned from this blog post.</p>
<h2>Summary</h2>
<p>This blog post has taught us four things:</p>
<ul>
<li>If we want to use the standard MockK API with Gradle, we have to add the <code>mockk</code> dependency to the <code>testImplementation</code> dependency configuration. We don't have to specify the variant we want to use because Gradle can read its own .module metadata and resolve the correct variant automatically.</li>
<li>If we want to use the standard MockK API with Maven, we have to add the <code>mockk-jvm</code> dependency to the <code>test</code> scope. We must explicitly specify the variant we want to use because Maven cannot read Gradle's .module metadata.</li>
<li>We must choose whether we want to couple our tests to a specific test instance lifecycle mode or ensure that our tests are working as expected regardless of the lifecycle configuration. This decision dictates how we can configure the system under test.</li>
<li>We must make a trade-off between automation and design feedback. The <code>MockKExtension</code> and annotations reduce boilerplate code, but the manual configuration acts as an architectural design tool which alerts us when a class has too many dependencies.</li>
</ul>
<p><strong>P.S. You can <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://github.com/pkainulainen/mockk-examples/tree/main/introduction">get the example application from Github</a></strong>.</p>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/programming/unit-testing/getting-started-with-mockk-the-setup/">Getting Started With MockK: The Setup</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/956061056/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/956061056/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/956061056/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/956061056/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/956061056/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/956061056/0/petrikainulainen~Getting-Started-With-MockK-The-Setup/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments></item>
<item>
<feedburner:origLink>https://www.petrikainulainen.net/monthly/software-development-monthly-4-2026/</feedburner:origLink>
		<title>Software Development Monthly 4 / 2026</title>
		<link>https://feeds.feedblitz.com/~/955802102/0/petrikainulainen~Software-Development-Monthly/</link>
					<comments>https://feeds.feedblitz.com/~/955802102/0/petrikainulainen~Software-Development-Monthly/#respond</comments>
		
		<dc:creator><![CDATA[Petri Kainulainen]]></dc:creator>
		<pubDate>Tue, 12 May 2026 15:10:46 +0000</pubDate>
				<category><![CDATA[Monthly]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[Spring Boot]]></category>
		<category><![CDATA[Spring Framework]]></category>
		<guid isPermaLink="false">https://www.petrikainulainen.net/?p=29120</guid>
					<description><![CDATA[<p>The Software Development Monthly is a monthly blog post that highlights interesting or useful blog posts which I read during the previous month. This blog post shares 24 interesting or useful blog posts which I read during April 2026. <a rel="NOFOLLOW" class="excerpt_read_more" href="/monthly/software-development-monthly-4-2026/">Read More</a></p>
<p>The post <a rel="NOFOLLOW" href="https://feeds.feedblitz.com/~/955802102/0/petrikainulainen~Software-Development-Monthly/">Software Development Monthly 4 / 2026</a> appeared first on <a rel="NOFOLLOW" href="https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/955802102/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/955802102/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/955802102/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/955802102/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</description>
										<content:encoded><![CDATA[<p>The Software Development Monthly is a monthly blog post that shares interesting or useful content which I consumed during the previous month. This blog post is always published on the eight day of the month.</p>
<p>Let's begin!</p>
<div class="note">
<strong>Table of Contents:</strong></p>
<ul>
<li><a href="#ai">AI</a></li>
<li><a href="#cloud">Cloud</a></li>
<li><a href="#sw-development">Software Development</a></li>
</ul>
</div>
<h2 id="ai">AI</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://sockpuppet.org/blog/2026/03/30/vulnerability-research-is-cooked/">Vulnerability Research Is Cooked</a> argues that a substantial amount of vulnerability research will be replaced with AI agents which will scan code bases for zero day vulnerabilities.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.hollandtech.net/claude-is-not-your-architect/">Claude Is Not Your Architect. Stop Letting It Pretend.</a> explains why we shouldn't let Claude (or any other AI agent) to sit on the driver's seat.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://futurism.com/artificial-intelligence/ai-boiling-frog-human-cognition-study">AI Use Appears to Have a "Boiling Frog" Effect on Human Cognition</a> summarizes the results of a research which claims that AI improves short term performance, but this improvement comes at a heavy cognitive cost.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://blog.jetbrains.com/idea/2026/03/ai-assisted-java-application-development-with-agent-skills/">AI-Assisted Java Application Development with Agent Skills</a> describes how we can optimize the context size by leveraging agent skills.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://spring.io/blog/2026/04/07/spring-ai-agentic-patterns-6-memory-tools">Spring AI Agentic Patterns (Part 6): AutoMemoryTools — Persistent Agent Memory Across Sessions</a> explains how we can give our AI agents a long-term memory that can be accessed by different sessions.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://spring.io/blog/2026/04/15/spring-ai-session-management">Spring AI Agentic Patterns (Part 7): Session API — Event-Sourced Short-Term Memory with Context Compaction</a> provides an introduction to Spring AI Session which adds support for storing the conversation history to a short-term memory. </p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://alexop.dev/posts/the-software-factory/">The Software Factory: Why Your Team Will Never Work the Same Again</a> explains how the rise of software factories is changing the way we write code.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://leehanchung.github.io/blogs/2026/04/05/the-ai-great-leap-forward/">The AI Great Leap Forward</a> argues that the current AI boom is a 'Great Leap Forward' that destroys software quality by prioritizing quantity and speed over human expertise.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.democratic-economy.org/total-skill-collapse-is-how-ai-makes-idiocracy-a-reality/">Total Skill Collapse Is How AI Makes Idiocracy a Reality</a> argues that AI model collapse is accelerated by the fact that no one has incentive to publish original content on the internet.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://larsfaye.com/articles/agentic-coding-is-a-trap">Agentic Coding is a Trap</a> explains that agentic coding is a trap because over time developers lose both the ability to write code and the deep system understanding required to maintain complex software.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://github.blog/news-insights/company-news/github-copilot-is-moving-to-usage-based-billing/">GitHub Copilot is moving to usage-based billing</a> announces that GitHub Copilot moves from flat-rate subscriptions to usage-based billing.</p>
<h2 id="cloud">Cloud</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.allthingsdistributed.com/2026/04/s3-files-and-the-changing-face-of-s3.html">S3 Files and the changing face of S3</a> introduces a new AWS feature called S3 files which allows us to use S3 as a network attached file system.</p>
<h2 id="sw-development">Software Development</h2>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://frederickvanbrabant.com/blog/2026-04-04-whats-in-it-for-me-architecture/">"What’s In It For Me" Architecture</a> argues that a good architect has excellent soft skills and provides three tips that help architects to convince other people to implement their designs.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://bold-edit.com/devlog/one-year-rewrite.html">A Year Long Rewrite</a> describes the challenges the author faced when they decided to rewrite the code of their text editor.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://jon.chrt.dev/2026/04/15/things-you-didnt-know-about-indexes.html">Things you didn't know about indexes</a> provides an introduction to database indexes and identifies some pitfalls which make our queries slower than they could be.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://purplesyringa.moe/blog/no-one-owes-you-supply-chain-security/">No one owes you supply-chain security</a> argues that open-source developers aren't responsible for the supply-chain security of the companies who profit from the open-source software.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://fagnerbrack.com/the-danger-of-modern-open-source-c15dd5206346">The Danger of "Modern" Open Source</a> examines the risks of the modern open-source ecosystem where companies exploit open-source maintainers for free. </p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://jvogel.me/posts/2026/java-is-fast-your-code-might-not-be">Java Is Fast. Your Code Might Not Be.</a> argues that the performance issues of Java applications are caused by inefficient coding patterns.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://jvogel.me/posts/2026/one-method-using-71-percent-of-cpu">One Method Was Using 71% of CPU. Here's the Flame Graph.</a> explains how we can investigate the performance of a Java application and demonstrates how the implementation of one method can lead to a massive bottleneck.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://blog.jbrains.ca/permalink/when-you-can-safely-leave-sprints-behind">When You Can Safely Leave Sprints Behind</a> argues that the traditional time-boxed sprints are useful when we are trying to build good habits, but we can move forward to continuous flow models once our workflow is stable and predictable.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://medium.com/all-things-software/spring-boot-configuration-properties-at-scale-884f494721ac">Spring Boot Configuration Properties at Scale</a> describes how we can manage complex Spring Boot configurations which are used by huge applications.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.infoq.com/articles/spring-team-spring-7-boot-4/">The Spring Team on Spring Framework 7 and Spring Boot 4</a> highlights the architectural and functional improvements introduced in Spring Framework 7 and Spring Boot 4.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://mitchellh.com/writing/ghostty-leaving-github">Ghostty Is Leaving GitHub</a> explains that Ghostly is leaving GitHub because of GitHub outages.</p>
<p><a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.sivalabs.in/before-you-judge-get-curious/">Before You Judge, Get Curious</a> describes why we should ask questions instead of judging people who disagree with us.</p>
<p>The post <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net/monthly/software-development-monthly-4-2026/">Software Development Monthly 4 / 2026</a> appeared first on <a href="https://feeds.feedblitz.com/~/t/0/0/petrikainulainen/~https://www.petrikainulainen.net">Petri Kainulainen</a>.</p>
<Img align="left" border="0" height="1" width="1" alt="" style="border:0;float:left;margin:0;padding:0;width:1px!important;height:1px!important;" hspace="0" src="https://feeds.feedblitz.com/~/i/955802102/0/petrikainulainen">
<div style="clear:both;padding-top:0.2em;"><a title="Like on Facebook" href="https://feeds.feedblitz.com/_/28/955802102/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/fblike20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Add to LinkedIn" href="https://feeds.feedblitz.com/_/16/955802102/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/linkedin20.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Post to X.com" href="https://feeds.feedblitz.com/_/24/955802102/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/x.png" style="border:0;margin:0;padding:0;"></a>&#160;<a title="Subscribe by RSS" href="https://feeds.feedblitz.com/_/20/955802102/PetriKainulainen"><img height="20" src="https://assets.feedblitz.com/i/rss20.png" style="border:0;margin:0;padding:0;"></a>&#160;</div>]]>
</content:encoded>
					
					<wfw:commentRss>https://feeds.feedblitz.com/~/955802102/0/petrikainulainen~Software-Development-Monthly/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments></item>
</channel></rss>

