mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-03-30 13:43:26 +08:00
feat(rules): add Java language rules (#645)
Adds Java language rules (coding-style, hooks, patterns, security, testing) following the established language rule conventions.
This commit is contained in:
131
rules/java/testing.md
Normal file
131
rules/java/testing.md
Normal file
@@ -0,0 +1,131 @@
|
||||
---
|
||||
paths:
|
||||
- "**/*.java"
|
||||
---
|
||||
# Java Testing
|
||||
|
||||
> This file extends [common/testing.md](../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
|
||||
|
||||
```java
|
||||
@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
|
||||
|
||||
```java
|
||||
@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:
|
||||
|
||||
```java
|
||||
@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.
|
||||
Reference in New Issue
Block a user