25. Unit Testing with JUnit and Mockito
When learning to program in Java, one of the most important aspects that a developer must master is the ability to write reliable and efficient tests. Unit testing is a fundamental part of software development, as it allows developers to verify the behavior of individual units of code (such as methods and classes) in isolation. In this chapter, we'll explore how you can write effective unit tests using the JUnit and Mockito libraries.
What are Unit Tests?
Unit tests are procedures that verify the functioning of a "unit" of code, which can be a method or an entire class. The goal is to ensure that each part of the software functions correctly independently, before being integrated with other parts of the system. This helps identify and fix errors at early stages of the development cycle, which can save time and resources.
Introduction to JUnit
JUnit is one of the most popular frameworks for writing unit tests in Java. It provides annotations and assertion methods to make it easier to verify expected code behavior. The latest version, JUnit 5, brings many improvements and new features compared to its predecessor, JUnit 4.
Writing a Simple Test with JUnit
To get started with JUnit, you need to create a test class. By convention, the name of this class is usually the name of the class that will be tested, followed by "Test". Inside this class, you will write methods annotated with @Test
, each representing a specific test case.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
@Test
void testSum() {
Calculator calc = new Calculator();
assertEquals(5, calc.sum(2, 3), "The sum must be 5");
}
}
In this example, the CalculadoraTest
class contains a test method testSum()
that checks whether the sum()
method of the class >Calculator
is working correctly. The assertEquals()
assertion is used to check whether the expected result (5) matches the result obtained when calling calc.somar(2, 3)
.
Mockito for Behavior Simulation
In many cases, the units of code that you want to test depend on other classes or resources that may be difficult to configure or that you do not want to invoke during unit tests. This is where Mockito comes into the picture. Mockito is a framework that allows you to create "mocks", which are simulations of real objects that can return specific data when their methods are called.
Using Mockito in Tests
To use Mockito, you will generally start by creating a mock for the dependent class using the mock()
method. You can then define the behavior of this mock with the when()
method, specifying what should be returned when specific methods are called.
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
class ServiceTest {
@Test
void testMethod() {
Dependency dependencyMock = mock(Dependency.class);
when(dependenciaMock.metodoDependente()).thenReturn("Simulated Value");
Service service = new Service(dependencyMock);
String result = servico.metodoASerTestado();
assertEquals("Expected Value", result);
}
}
In this example, we create a mock for the class Dependencia
and specify that, when the method metodoDependente()
is called, it should return "Simulated Value". This allows you to test the MetodoASerTestado()
method of the Servico
class without the need for an actual instance of the Dependencia
class.
Good Practices in Unit Testing
Writing effective unit tests is an art that requires practice and attention to detail. Here are some best practices to follow:
- Independence: Each test must be independent of the others. This means that running one test should not affect the result of another.
- Repeatability: A test must return the same result every time it is run, regardless of the environment or order of execution.
- Readability: Tests should be easy to read and understand. This helps other developers understand what is being tested and why.
- Code Coverage: Aim for good code coverage with your tests, but remember that test quality is more important than quantity.
- Test only the business logic: Avoid testing the infrastructureframework structure or programming language.
Unit testing is a powerful tool in any Java developer's arsenal. With practice, you will become increasingly efficient at writing tests that ensure the quality and reliability of your code. By using frameworks like JUnit and Mockito, you can simplify the testing process and focus on what really matters: creating robust, error-free software.