Developer-kit unit-test-utility-methods
Provides patterns for testing utility classes, static methods, and helper functions. Validates pure functions, null handling, edge cases, and boundary conditions. Generates AssertJ assertions and @ParameterizedTest for string utils, math utils, validators, and collection helpers. Use when testing utils, test helpers, helper functions, static methods, or verifying utility code correctness.
install
source · Clone the upstream repo
git clone https://github.com/giuseppe-trisciuoglio/developer-kit
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/giuseppe-trisciuoglio/developer-kit "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/developer-kit-java/skills/unit-test-utility-methods" ~/.claude/skills/giuseppe-trisciuoglio-developer-kit-unit-test-utility-methods && rm -rf "$T"
manifest:
plugins/developer-kit-java/skills/unit-test-utility-methods/SKILL.mdsource content
Unit Testing Utility Classes and Static Methods
Overview
This skill generates tests for utility classes with static helper methods and pure functions. It provides patterns for testing null handling, edge cases, boundary conditions, and common utilities like string manipulation, calculations, data validation, and collections. Pure functions require no mocking.
When to Use
Use this skill when:
- Writing tests for utility/helper classes with static methods
- Testing pure functions with no state or side effects
- Testing string manipulation, formatting, or transformation utilities
- Testing calculation, conversion, or math helper functions
- Testing data validation and formatter utilities
- Verifying null/empty input handling in utility code
- Testing collections or array helper methods
Instructions
- Create test class: Name it after the utility (e.g.,
)StringUtilsTest - Test happy path: Valid inputs with expected outputs
- Test edge cases: null, empty, whitespace, single elements
- Test boundary conditions: max/min values, large numbers, precision
- Use descriptive names:
instead ofshouldCapitalizeFirstLettertest1 - Use AssertJ: For readable, chainable assertions
- Use
: For multiple similar inputs (see@ParameterizedTest
)references/parameterized-tests.md - Avoid mocking: Pure utilities need no mocks
Examples
Basic Static Utility Test
import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.*; class StringUtilsTest { @Test void shouldCapitalizeFirstLetter() { assertThat(StringUtils.capitalize("hello")).isEqualTo("Hello"); } @Test void shouldReturnNullForNullInput() { assertThat(StringUtils.capitalize(null)).isNull(); } @Test void shouldHandleEmptyString() { assertThat(StringUtils.capitalize("")).isEmpty(); } @Test void shouldHandleSingleCharacter() { assertThat(StringUtils.capitalize("a")).isEqualTo("A"); } }
Comprehensive Example: isEmpty Implementation
// Input: public static boolean isEmpty(String str) // { return str == null || str.trim().isEmpty(); } class StringUtilsTest { @Test void shouldReturnTrueForNullString() { assertThat(StringUtils.isEmpty(null)).isTrue(); } @Test void shouldReturnTrueForEmptyString() { assertThat(StringUtils.isEmpty("")).isTrue(); } @Test void shouldReturnTrueForWhitespaceOnly() { assertThat(StringUtils.isEmpty(" ")).isTrue(); } @Test void shouldReturnFalseForNonEmptyString() { assertThat(StringUtils.isEmpty("hello")).isFalse(); } }
Null-Safe Utility
class NullSafeUtilsTest { @Test void shouldReturnDefaultWhenNull() { assertThat(NullSafeUtils.getOrDefault(null, "default")).isEqualTo("default"); } @Test void shouldReturnValueWhenNotNull() { assertThat(NullSafeUtils.getOrDefault("value", "default")).isEqualTo("value"); } @Test void shouldReturnFalseWhenBlank() { assertThat(NullSafeUtils.isNotBlank(null)).isFalse(); assertThat(NullSafeUtils.isNotBlank(" ")).isFalse(); } }
Math/Calculation Utility
class MathUtilsTest { @Test void shouldCalculatePercentage() { assertThat(MathUtils.percentage(25, 100)).isEqualTo(25.0); } @Test void shouldHandleZeroDivisor() { assertThat(MathUtils.percentage(50, 0)).isZero(); } @Test void shouldRoundToDecimalPlaces() { assertThat(MathUtils.round(3.14159, 2)).isEqualTo(3.14); } @Test void shouldHandleFloatingPointWithTolerance() { assertThat(MathUtils.multiply(0.1, 0.2)) .isCloseTo(0.02, within(0.0001)); } }
Collection Utility
class CollectionUtilsTest { @Test void shouldFilterList() { List<Integer> result = CollectionUtils.filter(List.of(1, 2, 3, 4), n -> n % 2 == 0); assertThat(result).containsExactly(2, 4); } @Test void shouldHandleNullList() { assertThat(CollectionUtils.filter(null, n -> true)).isEmpty(); } @Test void shouldJoinWithSeparator() { assertThat(CollectionUtils.join(List.of("a", "b", "c"), "-")).isEqualTo("a-b-c"); } @Test void shouldDeduplicateList() { assertThat(CollectionUtils.deduplicate(List.of("a", "b", "a"))) .containsExactlyInAnyOrder("a", "b"); } }
Data Validation Utility
class ValidatorUtilsTest { @Test void shouldValidateEmailFormat() { assertThat(ValidatorUtils.isValidEmail("user@example.com")).isTrue(); assertThat(ValidatorUtils.isValidEmail("invalid")).isFalse(); } @Test void shouldValidateUrlFormat() { assertThat(ValidatorUtils.isValidUrl("https://example.com")).isTrue(); assertThat(ValidatorUtils.isValidUrl("not a url")).isFalse(); } @Test void shouldValidateCreditCard() { assertThat(ValidatorUtils.isValidCreditCard("4532015112830366")).isTrue(); assertThat(ValidatorUtils.isValidCreditCard("1234567890123456")).isFalse(); } }
Utility with Clock Dependency (Rare)
@ExtendWith(MockitoExtension.class) class DateUtilsTest { @Mock private Clock clock; @Test void shouldGetDateFromClock() { when(clock.instant()).thenReturn(Instant.parse("2024-01-15T10:00:00Z")); assertThat(DateUtils.today(clock)).isEqualTo(LocalDate.of(2024, 1, 15)); } }
Best Practices
- Test pure functions exclusively - no side effects or state dependency
- Cover happy path and edge cases - null, empty, whitespace, extreme values
- Use descriptive test names -
shouldReturnNullWhenInputIsNull - Use
for multiple similar inputs (see@ParameterizedTest
)references/parameterized-tests.md - Test boundary conditions - min/max values, overflow, precision
- Avoid mocking pure functions - only mock external dependencies like Clock
- Keep tests independent - no order dependency between tests
Constraints and Warnings
- No mocking static methods: Use reflection utilities only when absolutely necessary
- Pure function requirement: Stateful utilities are harder to test; prefer immutability
- Floating point precision: Never use exact equality; use
isCloseTo(delta) - Null handling consistency: Decide whether utility returns null or throws; test accordingly
- Thread safety: Static utilities must be thread-safe; verify concurrent behavior separately
- Immutable inputs: Document whether utilities modify input parameters
- Edge cases reference: See
for boundary testing patternsreferences/edge-cases.md