{"id":388,"date":"2017-04-14T14:10:58","date_gmt":"2017-04-14T22:10:58","guid":{"rendered":"http:\/\/www.nathanbak.com\/?p=388"},"modified":"2026-01-02T20:04:41","modified_gmt":"2026-01-03T04:04:41","slug":"unit-testing-java-main-methods","status":"publish","type":"post","link":"https:\/\/nathanbak.com\/?p=388","title":{"rendered":"Unit testing Java main() methods"},"content":{"rendered":"<p>Most of the code I write does not go into Java main() methods and I&#8217;m quite accustomed to testing code in &#8220;normal&#8221; methods.\u00a0 Recently, however, I came across a situation where I needed to confirm a defect, verify a fix, and perform additional testing of a handful of edge cases related to the functionality of a main() method.\u00a0 In this post I describe the solution used.<\/p>\n<p>First, some disclaimers to help define the scope and also recognize that I&#8217;m doing a couple things that I would normally not consider best practices:<\/p>\n<ul>\n<li>Since the main() method is usually the entry to the entire application, running it normally involves a lot of code.\u00a0 In this case I want to only test the functionality of the code in the main() method itself and not the functionality of stuff that it calls&#8211;these are real unit tests.<\/li>\n<li>There are already many unit tests in place using JUnit so I want to continue using JUnit and be able to run everything together.<\/li>\n<li>Generally I think it&#8217;s poor form to to modify code to make it testable&#8211;code that is well-written should already be easy to test.\u00a0 However, I occasionally make exceptions such as making a method protected instead of private in order to expose it to testing (I think that&#8217;s a lot cleaner than using reflection to run a private method).<\/li>\n<\/ul>\n<p>So, here&#8217;s a very simplified example of the class with which I started (note that the non-main methods are not implemented):<\/p>\n<pre>package com.nathanbak.test.main;\n\npublic class Application {\n\n\u00a0\u00a0 \u00a0protected Application() { }\n\n\u00a0\u00a0 \u00a0public static void main(String[] args) {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0String string = args[0];\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Application application = new Application();\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0try {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0application.run(string);\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} catch (Exception e) {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0System.out.println(e.getMessage());\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0System.exit(1);\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0System.exit(0);\n\u00a0\u00a0 \u00a0}\n\u00a0\u00a0 \u00a0\n\u00a0\u00a0 \u00a0protected void run(String string) throws Exception { }\n\u00a0\u00a0 \u00a0\n\u00a0\u00a0 \u00a0protected void logException() { }\n}<\/pre>\n<p>I try to avoid putting much code in main() methods, but typically end up having things like:<\/p>\n<ul>\n<li>Parsing\/validating arguments (something the above example does poorly)<\/li>\n<li>Object instantiation<\/li>\n<li>Running of object methods (often with arguments)<\/li>\n<li>Providing some sort of top level exception handling and user output<\/li>\n<li>Provide a relevant exit code (typically 0 for success and 1 for failure)<\/li>\n<\/ul>\n<p>When I tried creating JUnits for the main() method, here are some problems I encountered:<\/p>\n<ol>\n<li>If a test called the main() method, the test run would halt because of the System.exit() call.<\/li>\n<li>Verifying output to System.out is difficult.<\/li>\n<li>Running the main() method means running the run() method which can take a long time and changes the scope of the test.<\/li>\n<li>It&#8217;s hard to test edge cases (such as what if the run() method throws an exception that doesn&#8217;t have any message).<\/li>\n<\/ol>\n<p>I was worried that #1 was going to be a deal breaker, but fortunately found an easy solution in <a href=\"http:\/\/stefanbirkner.github.io\/system-rules\/\">System Rules<\/a> which bills itself as &#8220;A collection of JUnit rules for testing code that uses java.lang.System.&#8221;\u00a0 I added the system-rules-1.16.0.jar to my classpath, followed the examples on the main page, and had a great solution to #1 and #2 above (as well as solutions to various other problems I hadn&#8217;t considered but will keep in mind for the future).<\/p>\n<p>To cover #3 and #4 above was where I had to get a bit more unorthodox.\u00a0 I created a private static method that creates and returns the new object and replaced the constructor in the main() method with a call to that new method.\u00a0 I also added a protected static property that I could use to store an instance and had my new static method use that instance if it was not null.\u00a0 This is now my class turned out:<\/p>\n<pre>package com.nathanbak.test.main;\n\npublic class Application {\n\n\u00a0\u00a0 \u00a0protected Application() { }\n\n\u00a0\u00a0 \u00a0public static void main(String[] args) {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0String string = args[0];\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0Application application = newApplication();\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0try {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0application.run(string);\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0} catch (Exception e) {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0System.out.println(e.getMessage());\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0System.exit(1);\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0System.exit(0);\n\u00a0\u00a0 \u00a0}\n\u00a0\u00a0 \u00a0\n\u00a0\u00a0 \u00a0protected void run(String string) throws Exception { }\n\u00a0\u00a0 \u00a0\n\u00a0\u00a0 \u00a0protected void logException() { }\n\n\u00a0\u00a0 \u00a0protected static Application instance = null;\n\u00a0\u00a0 \u00a0\n\u00a0\u00a0 \u00a0private static Application newApplication() {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0return instance == null ? new Application() : instance;\n\u00a0\u00a0 \u00a0}\n}<\/pre>\n<p>With the ability to control the object used to run methods, I was able to create tests like:<\/p>\n<pre>package com.nathanbak.test.main;\n\nimport static org.junit.Assert.*;\nimport org.junit.After;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.contrib.java.lang.system.ExpectedSystemExit;\n\npublic class ApplicationTest extends Application {\n\n\u00a0\u00a0 \u00a0@After\n\u00a0\u00a0 \u00a0public void tearDown() throws Exception {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0instance = null;\n\u00a0\u00a0 \u00a0}\n\u00a0\u00a0 \u00a0\n\u00a0\u00a0 \u00a0@Rule\n\u00a0\u00a0 \u00a0public final ExpectedSystemExit exit = ExpectedSystemExit.none();\n\n\u00a0\u00a0 \u00a0@Test\n\u00a0\u00a0 \u00a0public void testMain() {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0instance = new CrashAndBurn();\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0String [] args = { \"one\", \"two\", \"three\" };\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0exit.expectSystemExitWithStatus(1);\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0main(args);\n\u00a0\u00a0 \u00a0}\n\u00a0\u00a0 \u00a0\n\u00a0\u00a0 \u00a0private static class CrashAndBurn extends Application {\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0@Override\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0protected void run(String string) throws Exception { \n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0throw new Exception();\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0}\n\u00a0\u00a0 \u00a0}\n}<\/pre>\n<p>A few things to note about the test class:<\/p>\n<ul>\n<li>The test class needs to extend the class under test in order to have access to the instance property.<\/li>\n<li>The testMain() test currently calls main with some args and then the CrashAndBurn class throws an exception when the run() method is called and the test confirms that the main() method returns an exit code of 1 (the test would fail if any other exit code was returned).<\/li>\n<li>The tearDown() method sets the instance back to null after every test to ensure that specific instances are only used when desired for specific tests.<\/li>\n<\/ul>\n<p>Obviously my real tests are more numerous and comprehensive, but the above example shows how I was able to overcome the difficulties encountered when trying to create unit tests for a Java main() method.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Most of the code I write does not go into Java main() methods and I&#8217;m quite accustomed to testing code in &#8220;normal&#8221; methods.\u00a0 Recently, however, I came across a situation where I needed to confirm a defect, verify a fix, and perform additional testing of a handful of edge cases related to the functionality of &hellip; <a href=\"https:\/\/nathanbak.com\/?p=388\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Unit testing Java main() methods&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-388","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts\/388","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=388"}],"version-history":[{"count":6,"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts\/388\/revisions"}],"predecessor-version":[{"id":721,"href":"https:\/\/nathanbak.com\/index.php?rest_route=\/wp\/v2\/posts\/388\/revisions\/721"}],"wp:attachment":[{"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=388"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=388"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nathanbak.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=388"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}