mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 13:43:26 +08:00
Adds Java language rules (coding-style, hooks, patterns, security, testing) following the established language rule conventions.
3.4 KiB
3.4 KiB
paths
| paths | |
|---|---|
|
Java Testing
This file extends common/testing.md with Java-specific content.
Test Framework
- JUnit 5 (
@Test,@ParameterizedTest,@Nested,@DisplayName) - AssertJ for fluent assertions (
assertThat(result).isEqualTo(expected)) - Mockito for mocking dependencies
- Testcontainers for integration tests requiring databases or services
Test Organization
src/test/java/com/example/app/
service/ # Unit tests for service layer
controller/ # Web layer / API tests
repository/ # Data access tests
integration/ # Cross-layer integration tests
Mirror the src/main/java package structure in src/test/java.
Unit Test Pattern
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock
private OrderRepository orderRepository;
private OrderService orderService;
@BeforeEach
void setUp() {
orderService = new OrderService(orderRepository);
}
@Test
@DisplayName("findById returns order when exists")
void findById_existingOrder_returnsOrder() {
var order = new Order(1L, "Alice", BigDecimal.TEN);
when(orderRepository.findById(1L)).thenReturn(Optional.of(order));
var result = orderService.findById(1L);
assertThat(result.customerName()).isEqualTo("Alice");
verify(orderRepository).findById(1L);
}
@Test
@DisplayName("findById throws when order not found")
void findById_missingOrder_throws() {
when(orderRepository.findById(99L)).thenReturn(Optional.empty());
assertThatThrownBy(() -> orderService.findById(99L))
.isInstanceOf(OrderNotFoundException.class)
.hasMessageContaining("99");
}
}
Parameterized Tests
@ParameterizedTest
@CsvSource({
"100.00, 10, 90.00",
"50.00, 0, 50.00",
"200.00, 25, 150.00"
})
@DisplayName("discount applied correctly")
void applyDiscount(BigDecimal price, int pct, BigDecimal expected) {
assertThat(PricingUtils.discount(price, pct)).isEqualByComparingTo(expected);
}
Integration Tests
Use Testcontainers for real database integration:
@Testcontainers
class OrderRepositoryIT {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16");
private OrderRepository repository;
@BeforeEach
void setUp() {
var dataSource = new PGSimpleDataSource();
dataSource.setUrl(postgres.getJdbcUrl());
dataSource.setUser(postgres.getUsername());
dataSource.setPassword(postgres.getPassword());
repository = new JdbcOrderRepository(dataSource);
}
@Test
void save_and_findById() {
var saved = repository.save(new Order(null, "Bob", BigDecimal.ONE));
var found = repository.findById(saved.getId());
assertThat(found).isPresent();
}
}
For Spring Boot integration tests, see skill: springboot-tdd.
Test Naming
Use descriptive names with @DisplayName:
methodName_scenario_expectedBehavior()for method names@DisplayName("human-readable description")for reports
Coverage
- Target 80%+ line coverage
- Use JaCoCo for coverage reporting
- Focus on service and domain logic — skip trivial getters/config classes
References
See skill: springboot-tdd for Spring Boot TDD patterns with MockMvc and Testcontainers.
See skill: java-coding-standards for testing expectations.