Skip to content
Josh Grant4 min read

How To Do Unit Testing In Java

Unit testing is a crucial aspect of software development and helps to ensure that individual units of code are working as intended. In Java, the most popular framework for unit testing is JUnit. In this article, we will go over the basics of how to write and run unit tests in Java using the popular testing framework, as well as some best practices for unit testing.

iunit-testing-in-java

Getting Started with JUnit

To get started with JUnit, you will first need to add the JUnit library to your project. This can typically be done by adding the JUnit dependency to your build tool of choice (such as Maven or Gradle). Once the library is added, you can start writing your tests.

A JUnit test is simply a method that is annotated with the @Test annotation. The method should contain the code you want to test and any assertions that check the expected results.

public class InformationDatabaseTest {

    private InformationDatabase db;

    @Test
    public void insertDataUnitTest(){ 

  }
}

One approach to write a good test is to use the “arrange, act, assert” pattern:

public class InformationDatabaseTest {

    private InformationDatabase db;

    @Test
    public void insertDataUnitTest(){ 
// arrange our objects and test fixtures
// act on an object to perform a test
// assert the result of the action is as expected
  }
}

Running Your Tests

Once you have written your tests, you can run them using the JUnit runner. The runner will automatically discover and run all of the methods annotated with @Test. The results of the tests will be displayed in the console and can also be generated in a variety of formats (such as HTML or XML) for easy integration with continuous integration tools.

An example of a fully written test may look like this:

public class InformationDatabaseTest {

    private InformationDatabase db;

    private InformationDatabase initializeDatabase(){
        InformationDatabase db = new InformationDatabase();
        db.connect();
        return db;
    }

    @Test
    public void insertDataUnitTest(){ 
        // arrange our objects and test fixtures
        db = initializeDatabase(); // initialize db object to test
        Road road = new Road("Germany"); // create a valid Road object to insert into db
        // act on an object to perform a test
Boolean result = db.insertRoadData(road);

        // assert the result of the action is as expected
Assert.assertTrue(result);
    }
}

Best Practices for Unit Testing

Keep your tests small and focused: Each test should only test one specific behavior or feature of your code. If a test is testing multiple things at once, it becomes harder to understand what is causing a failure when one occurs.

Use meaningful test names: The name of a test should clearly indicate what the test is testing. This makes it easier to understand the purpose of the test and what it is checking for.

Avoid testing implementation details: The purpose of unit tests is to test the behavior of the code, not the implementation details. Avoid testing things like the specific algorithm used in a method, as these details can change without affecting the behavior of the code.

Use test data that covers a range of cases: When writing tests, it's important to test a variety of different input values to ensure that your code is handling all possible cases correctly. This is especially important when testing edge cases (such as input that is at the maximum or minimum value).

Use test doubles: Test doubles, such as mocks and stubs, can be used to isolate the code being tested from other parts of the system. This makes it easier to write tests that are focused on specific behavior while making them faster and more reliable.

By following the best practices above, you can make your tests more effective at finding bugs and other issues in your code. Additionally, by incorporating fuzz testing into your testing process, you can also help to uncover issues that unit tests tend to miss.

Adding Fuzz Tests in JUnit

Fuzz testing is a technique used to find security vulnerabilities in software by providing unexpected or malformed input to the software. JUnit can be used to perform fuzz tests, during which test cases are created that supply random or malformed input to the methods under test. This complements unit tests, as fuzzing is non-deterministic, meaning that fuzzing engines can generate random or unexpected inputs, that go beyond the things unit tests normally test for.

The code snippet below shows how these two testing methods complement each other. The @Test annotation calls a unit test aimed to ensure that the application handles valid inputs gracefully. Below, you can see the @FuzzTest annotation, which uses the FuzzedDataProvider to generate random and invalid inputs to assert if any of them trigger unusual behavior.

public class InformationDatabaseTest {

    private InformationDatabase db;

    private InformationDatabase initializeDatabase(){
        InformationDatabase db = new InformationDatabase();
        db.connect();
        return db;
    }

    @Test
    public void insertDataUnitTest(){ 
        // arrange our objects and test fixtures
        db = initializeDatabase(); // initialize db object to test
        Road road = new Road("Germany"); // create a valid Road object to insert into db
        // act on an object to perform a test
        Boolean result = db.insertRoadData(road);
        // assert the result of the action is as expected
        Assert.assertTrue(result);
    }

    @FuzzTest
    public void insertDataFuzzTest(FuzzedDataProvider fuzzedData){
        // arrange our objects and test fixtures
        db = initializeDatabase(); // initialize db object to test
        Road road = new Road(fuzzedData.consumeString(10)); // generate fuzzy inputs
        // act on an object to perform a test
        Boolean result = db.insertRoadData(road);
        // assert the result of the action is as expected
        Assert.assertTrue(result);
    }
}

Running Fuzz Tests and Unit Tests in RoadSmart

In the code example above, we use both unit tests and fuzz tests within the JUnit testing framework to test RoadSmart, a demo application that is meant to provide information about roads all over the world. The example illustrates how these two testing methods can be applied in unison and shows the different types of issues they can find.