Skip to main content

Testing with JUnit and Build Tools (Maven and Gradle)

Build tools​

ToolConfig fileNotes
Mavenpom.xmlConvention over configuration; huge ecosystem
Gradlebuild.gradle(.kts)Flexible, fast incremental builds
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.prepverse</groupId>
<artifactId>notes</artifactId>
<version>1.0.0</version>

<properties>
<maven.compiler.release>21</maven.compiler.release>
</properties>

<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
mvn clean test # compile and run tests
mvn package # build the jar

Standard layout: src/main/java, src/main/resources, src/test/java.

JUnit 5 tests​

import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;

class CartTest {
private Cart cart;

@BeforeEach
void setUp() { cart = new Cart(); }

@Test
void emptyCartHasZeroTotal() {
assertEquals(0.0, cart.total(), 0.0001);
}

@Test
void addsItemPrices() {
cart.add(new Item("pen", 10));
cart.add(new Item("book", 25));
assertEquals(35.0, cart.total(), 0.0001);
}

@Test
void rejectsNegativePrice() {
assertThrows(IllegalArgumentException.class, () -> new Item("x", -1));
}
}

Parameterised tests​

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

class MathTest {
@ParameterizedTest
@CsvSource({"1,2,3", "0,0,0", "-5,5,0"})
void adds(int a, int b, int expected) {
assertEquals(expected, a + b);
}
}

Mocking with Mockito​

import static org.mockito.Mockito.*;

class OrderServiceTest {
@Test
void chargesThePaymentGateway() {
PaymentGateway gateway = mock(PaymentGateway.class);
when(gateway.charge(anyDouble())).thenReturn(true);

OrderService service = new OrderService(gateway);
assertTrue(service.checkout(49.99));

verify(gateway).charge(49.99);
}
}

Testing guidelines​

  • Test behaviour, not implementation details; keep tests fast and independent.
  • Name tests by the scenario and expected outcome.
  • Mock only boundaries (network, database, clock), not your own simple classes.
  • Run tests in CI on every push (see Testing and deployment).