Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Unit Testing | Testing in Development
course content

Зміст курсу

Java JUnit Library. Types of Testing

Unit TestingUnit Testing

Let's take a closer look at the concept of unit testing and why it's necessary.

Unit testing in Java is the process of developing and executing tests for individual modules or "units" of source code. The goal of such testing is to ensure that each module functions correctly. The primary tool for unit testing in Java is the JUnit framework.

JUnit Basics

JUnit is a framework for unit testing that provides annotations for defining test methods and assertions to check expected results.

You've already encountered annotations when overriding different methods. In simple terms, annotations tell the compiler or framework what to do with a particular module. They also provide information to the programmer about the meaning of a specific line or module in the program. Annotations greatly simplify life and are used in almost every framework. Let's take a look at a simple example of a unit test, and you'll understand how annotations are used:

In this example:

  • The @Test annotation indicates that the method testAddition() is a test method;
  • Calculator is the class we are testing;
  • Assertions.assertEquals(8, result) checks that the addition result equals 8.

Therefore, we have verified that the add() method correctly performs its function. However, a single unit test is not sufficient, as there could be many other issues. For example, a user might pass null instead of a number, or the numbers could fall outside the acceptable range. Such cases should also be covered by unit tests.

Note

We will delve into writing and learning unit tests in the next section. This chapter is designed for informational purposes and to help you understand why writing unit tests is necessary.

What should unit tests check?

Let's imagine that we need to test a simple method. For this purpose, we will write a method that takes a string in the form of
"Name||Address||email||phoneNumber||" and splits it into a map with corresponding keys and values.

This method code will look something like this:

java

Main.java

Code Description
This Java code features a Main class that includes a method convertToMap for converting a structured string into a map:

  • Imports: Utilizes HashMap and Map from the java.util package;

  • Class Definition: The Main class is defined as public;

  • Method convertToMap:
  • - Takes a string as input, splits it into parts using "||" as the delimiter, and stores these parts in a Map with predefined keys ("Name", "Address", "Email", "PhoneNumber");

  • Main Method:
  • - Creates a test string, calls convertToMap to convert it to a map, and prints the map to the console;

    The code essentially parses a delimited string into a map structure, making it easy to access individual data components using their corresponding keys.

    Note

    To split this format, we need to split by the || symbol, but we must indicate to the compiler that it is indeed a symbol and not a command. Therefore, we use \\ before the symbol. Thus, our regex looks like this: \\|\\|.

    The method is quite simple to write. But let's now return to what exactly test cases exist for this method:

    • Test of Correct Data Testing with correctly formatted input string. Expecting the method to return a Map with the correct values for each key;
    • Test of Incorrect Format Testing with a string that does not match the expected format (e.g., missing some of the required || separators or having them in excess);
    • Test of Empty String Checking the method's behavior when the input string is empty. The method should either return an empty Map or throw an exception;
    • Test of Null String Testing the method's behavior when null is passed as the input string.

    Let's go step by step. In the first test case, we will test the functioning of this method with correct data. In the main method, we have already done this when we passed a value and received the correct data.

    In the second test case, we need to pass an incorrect format to see how the method will behave. For example, let's pass data separated by a single | character:

    java

    main.java

    As you can see, we are throwing an IndexOutOfBoundsException. This means that the array we create from the original string does not have 4 elements as it should have. The test showed us that our method is not perfect, so let's add exception handling using a simple if statement:

    Here, we've added a basic check that, in case incorrect data is passed, will return an empty map and print a message about the method's incorrect operation.

    Let's look at a runnable example:

    java

    main.java

    As you can see, the third test case is also covered by this check; If an empty string is passed, it won't pass the validation we wrote.

    Let's move on to the case where a null value is passed. We don't currently check the string for null, so we need to add this check in the method:

    We have added a null check, and now the method will return an empty map if null is passed to it.

    Let's run this code and see the result:

    java

    main.java

    So, we have a refined method that handles various errors and different parameter-passing cases. We tested this method manually without using the JUnit library. However, in the next section, we will do this much faster using this library and unit tests.

    Все було зрозуміло?

    Секція 1. Розділ 4
    course content

    Зміст курсу

    Java JUnit Library. Types of Testing

    Unit TestingUnit Testing

    Let's take a closer look at the concept of unit testing and why it's necessary.

    Unit testing in Java is the process of developing and executing tests for individual modules or "units" of source code. The goal of such testing is to ensure that each module functions correctly. The primary tool for unit testing in Java is the JUnit framework.

    JUnit Basics

    JUnit is a framework for unit testing that provides annotations for defining test methods and assertions to check expected results.

    You've already encountered annotations when overriding different methods. In simple terms, annotations tell the compiler or framework what to do with a particular module. They also provide information to the programmer about the meaning of a specific line or module in the program. Annotations greatly simplify life and are used in almost every framework. Let's take a look at a simple example of a unit test, and you'll understand how annotations are used:

    In this example:

    • The @Test annotation indicates that the method testAddition() is a test method;
    • Calculator is the class we are testing;
    • Assertions.assertEquals(8, result) checks that the addition result equals 8.

    Therefore, we have verified that the add() method correctly performs its function. However, a single unit test is not sufficient, as there could be many other issues. For example, a user might pass null instead of a number, or the numbers could fall outside the acceptable range. Such cases should also be covered by unit tests.

    Note

    We will delve into writing and learning unit tests in the next section. This chapter is designed for informational purposes and to help you understand why writing unit tests is necessary.

    What should unit tests check?

    Let's imagine that we need to test a simple method. For this purpose, we will write a method that takes a string in the form of
    "Name||Address||email||phoneNumber||" and splits it into a map with corresponding keys and values.

    This method code will look something like this:

    java

    Main.java

    Code Description
    This Java code features a Main class that includes a method convertToMap for converting a structured string into a map:

  • Imports: Utilizes HashMap and Map from the java.util package;

  • Class Definition: The Main class is defined as public;

  • Method convertToMap:
  • - Takes a string as input, splits it into parts using "||" as the delimiter, and stores these parts in a Map with predefined keys ("Name", "Address", "Email", "PhoneNumber");

  • Main Method:
  • - Creates a test string, calls convertToMap to convert it to a map, and prints the map to the console;

    The code essentially parses a delimited string into a map structure, making it easy to access individual data components using their corresponding keys.

    Note

    To split this format, we need to split by the || symbol, but we must indicate to the compiler that it is indeed a symbol and not a command. Therefore, we use \\ before the symbol. Thus, our regex looks like this: \\|\\|.

    The method is quite simple to write. But let's now return to what exactly test cases exist for this method:

    • Test of Correct Data Testing with correctly formatted input string. Expecting the method to return a Map with the correct values for each key;
    • Test of Incorrect Format Testing with a string that does not match the expected format (e.g., missing some of the required || separators or having them in excess);
    • Test of Empty String Checking the method's behavior when the input string is empty. The method should either return an empty Map or throw an exception;
    • Test of Null String Testing the method's behavior when null is passed as the input string.

    Let's go step by step. In the first test case, we will test the functioning of this method with correct data. In the main method, we have already done this when we passed a value and received the correct data.

    In the second test case, we need to pass an incorrect format to see how the method will behave. For example, let's pass data separated by a single | character:

    java

    main.java

    As you can see, we are throwing an IndexOutOfBoundsException. This means that the array we create from the original string does not have 4 elements as it should have. The test showed us that our method is not perfect, so let's add exception handling using a simple if statement:

    Here, we've added a basic check that, in case incorrect data is passed, will return an empty map and print a message about the method's incorrect operation.

    Let's look at a runnable example:

    java

    main.java

    As you can see, the third test case is also covered by this check; If an empty string is passed, it won't pass the validation we wrote.

    Let's move on to the case where a null value is passed. We don't currently check the string for null, so we need to add this check in the method:

    We have added a null check, and now the method will return an empty map if null is passed to it.

    Let's run this code and see the result:

    java

    main.java

    So, we have a refined method that handles various errors and different parameter-passing cases. We tested this method manually without using the JUnit library. However, in the next section, we will do this much faster using this library and unit tests.

    Все було зрозуміло?

    Секція 1. Розділ 4
    some-alt