Setting Up Unit Testing For Java In VS Code (with Maven)

Karl Rombauts
9 min readApr 5, 2020

Today I found out about this really neat extension for VS Code called code gutters Coverage Gutters. So I thought cool let’s install that. A few hours later down the rabbit hole, I have learnt a lot about setting up unit testing in VS Code for Java. So I thought, why not share what I learnt for others who want to do the same.

Step 1: Install Relevant Java Extensions

The Java Extension Pack is basically everything that you are going to need to get up and running with Java in VS Code. This pack will install the following extensions for you. Feel free to also install them individually if you like

And then we will obviously need the Coverage Gutters extension also.

Cool, that is all there is to it for extensions. Let’s move on to the next part!

Step 2: Let’s start a new Java project

We will be using Maven for the rest of this article. If you haven’t used maven before here is a quick guide by free code camp.

The Maven for Java extension that came bundled in the Java Extension Pack makes setting up a new Maven project super simple! just type ctrl/cmd + shift + p to bring up the command palette. and select Maven: Create Maven Project

Then you will be prompted to select an archetype. If you don’t know, an archetype is like a basic template that installs all the things that you might need and sets up your projects for you.

We will be using the maven-archetype-quickstart. It will then prompt you for a version number. Just select the latest one, at the time of writing the latest version is 1.4.

It will then prompt you to select a destination folder. This is the folder that will contain your project folder. In my case, I choose my java-projects folder as the destination.

At this point, a terminal should pop up, and your project will start building. Once that is done, it will prompt you for some details.

Define value for property 'groupId': com.[your-domain].[project-name]

The groupId is meant to be a unique value for your project. So using your domain name (if you have one) is usually standard practice. But if you don’t plan on publishing this, it can really be whatever you want.

Define value for property 'artifactId': project-name

You can set the artifactId to your project name. I will be using VsCodeJavaUnitTests.

Define value for property 'version' 1.0-SNAPSHOT: :

For your version, you can just select the default value by hitting enter.

Define value for property 'package' com.karlrombauts.VsCodeJavaUnitTests: :

It will suggest a package name based on the group id you entered earlier. Again you can select the default by hitting enter.

Finally, it will ask you to confirm by typing Y.

Great! Your maven project is setup :)

Now if you navigate to the destination folder you chose in the previous step, you will see you new project. You can now open this in VS code and we’ll get started with the next step.

Step 3: Correct Folder Structure

Your folder structure will be a bit different depending on the package name you gave in the previous step.

There are two main things that are important here:

  1. your project has a main folder and a test in the src folder
  2. Inside both these folders you should have the same folder structure.
$ tree.
├── pom.xml
└── src
├── main
│ └── java
│ └── com
│ └── karlrombauts
│ └── VsCodeJavaUnitTests
│ └── App.java
└── test
└── java
└── com
└── karlrombauts
└── VsCodeJavaUnitTests
└── AppTest.java

You will also see that in the main folder structure you have a file called App.java, and in the test folder structure you have a file called AppTest.java. This is also important. Maven will automatically look for files with the *Test.java suffix when running tests. So a good convention to stick to is naming your test files [ClassName]Test.java.

Now, as you can see, my folder structure is missing the .classpath and .project files as well as a /target folder. You might already have these files, in which case just skip to the next step :)

This might be for two reasons; either VS Code is hiding these files for you, or they have not been generated automatically.

Lets first make sure they are not being hidden. Open your settings UI and search for Files: Exclude

If you see mention of .classpath, .project or target/ just remove them from the list by clicking on the x on the right.

If they are still not showing up in the explorer reload the window. To do this press ctrl/cmd + shift + p to bring up the command palette and type reload window

This will prompt VS to regenerate your java files.

Great, Now that we are set up, let’s move on!

Note: If you have an existing project

You can simply put all the files and folders of your existing project into a similar folder structure. Make sure that you create the same folder structure for your test folder. You will also have to update some of your package names in your java files.

Step 4: Upgrade to JUnit5

Open up your pom.xml file and in the <dependencies> section and replace

This:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>

With this:

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.4.2</version>
<scope>test</scope>
</dependency>

If this is your first time dealing with a pom.xml file fear not, it is not as scary as it looks. The dependencies section is just telling Maven what you want to install. In this vase we want junit-jupiter-api version 5.4.2 and junit-jupiter-engine version 5.4.2. You will notice that each dependency has a groupId, artifactId and version. Just like we set up for our project. Each dependency also has a scope. You can read more about scope from this great Stack Overflow answer: https://stackoverflow.com/a/29230903

After editing your pom.xml file, you should be prompted with this message:

You can either choose Now or Always, and it will go ahead and update your classpath configuration. Now will only update your configuration this time, while Always will automatically update the configuration each time you modify the pom.xml file in the future.

Finally, change the import statements in AppTest.java to the new JUnit5:

import static org.junit.jupiter.api.Assertions.assertTrue;import org.junit.jupiter.api.Test;

Sweet, JUnit5 is now installed. Let’s keep going :)

Step 5: Write some tests

This will be very project specific, so I will just do a very simple demo. This is by no means meant to be a unit testing tutorial, just how to set unit tests up in VS Code.

BankAccount.java
This is a VERY basic bank account class inside the main folder structure.

package com.karlrombauts.VsCodeJavaUnitTests;public class BankAccount {
private int balance = 0;
public BankAccount(int startingBalance) {
this.balance = startingBalance;
}
public boolean withdraw(int amount) {
if(balance >= amount) {
balance -= amount;
return true;
}
return false;
}
public int deposit(int amount) {
balance += amount;
return balance;
}
public int getBalance() {
return balance;
}
}

BankAccountTest.java
This is included in the test folder structure. In this file we will write all our unit tests. Lets write a very simple one for now.

package com.karlrombauts.VsCodeJavaUnitTests;import static org.junit.jupiter.api.Assertions.assertTrue;import org.junit.jupiter.api.Test;public class BankAccountTest {
@Test
public void withdraw_returnsTrue_ifEnoughFunds() {
BankAccount account = new BankAccount(500);
assertTrue(account.withdraw(400));
}
}

This test will check if you can withdraw 400 from an account that has a balance of 500. Which should return true.

Now thanks to our handy dandy Java Test Runner we can run these tests without the need of the command line.

You can simply click on the Run Test and Debug Test shortcuts

Or in the test explorer, you can view all your tests and run them.

Cool, so let’s give our tests a whirl to make sure everything passes and let’s move on to the next step.

Note: If you can’t see your tests in the Test Explorer and the shortcut are not showing up…

This was an issue that I came across when I was setting this up. Firstly check that you have the right folder structure as described in the previous steps. By default VS Code will be looking for your tests in src/test/java/...

Then go check out .classpath and make sure it contains:

<classpathentry kind="src" path="src/test/java" output="build/classes/test">
<attributes>
<attribute name="test" value="true" />
</attributes>
</classpathentry>

For more on this issue: https://github.com/Microsoft/vscode-java-test/issues/470

Step 6: Code Coverage!

Finally, we are up to the step that kick started all of this. We have our tests running. Now it would be nice to see how much of our code our tests are covering. Luckily this is “relatively” easy to set up. I put relatively in quotes because I spent 4 hours trying to get this to work, but I will help guide you so that you don’t make the same mistakes that I did.

We need to install some maven plugins. Crack open your pom.xml file again and add the following between the <plugins>...</plugins> tags.

<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.4</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>prepare-package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>

JaCoCo (Java Code Coverage) is a plugin that will generate a report of your code coverage.

Now ready for some magic? Run this in your terminal:

mvn jacoco:prepare-agent test install jacoco:report

If all goes well (troubleshooting tips down below), you will now have a new file target/site/jacoco/index.html This is the code coverage report of your tests. You can open this in your preferred web browser.

And just like that, you have a very detailed report of your code coverage. BUT we can do better still.

If you have installed Coverage Gutters, in your status bar at the bottom left you will see something that says Watch.

Click on that to turn watch on. And then go check out the class you wrote tests for (in my case BankAccount.java)

Green bars indicate that that code has been reached by your tests.
Orange bars indicate a missed conditional check.
Red bars indicate code that was not reached by your tests.

This is helpful because this shows us that we have tested the case where the withdraw method returns true, but we haven’t tested the case where it returns false.

Note: If you ran into any errors…

First, make sure there are no errors in your code. Second make sure you that you upgrade both maven-surefire-plugin, and jacoco-maven-plugin to their latest versions. I kept getting errors when trying to set this up and ended up being an issue with old versions.

Step 7: Update your tests

I’ve added these two tests to the BankAccountTest.java file.

@Test
public void withdraw_returnsTrue_ifWithdrawingAllFunds() {
BankAccount account = new BankAccount(500);
assertTrue(account.withdraw(500));
}
@Test
public void withdraw_returnsFalse_ifNotEnoughFunds() {
BankAccount account = new BankAccount(500);
assertFalse(account.withdraw(600));
}

Now lets run the command again:

mvn jacoco:prepare-agent test install jacoco:report

And just like that out code coverage gutters are updated.

You’re done!

Great job! If you’ve never used maven before, then that’s even better! I hope this article helped you and happy testing!

--

--