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.
Works with
---
name: unit-test-utility-methods
description: 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.
license: MIT
---
# 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
1. **Create test class**: Name it after the utility (e.g., `StringUtilsTest`)
2. **Test happy path**: Valid inputs with expected outputs
3. **Test edge cases**: null, empty, whitespace, single elements
4. **Test boundary conditions**: max/min values, large numbers, precision
5. **Use descriptive names**: `shouldCapitalizeFirstLetter` instead of `test1`
6. **Use AssertJ**: For readable, chainable assertions
7. **Use `@ParameterizedTest`**: For multiple similar inputs (see `references/parameterized-tests.md`)
8. **Avoid mocking**: Pure utilities need no mocks
## Examples
### Basic Static Utility Test
```java
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
```java
// 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
```java
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
```java
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
```java
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
```java
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)
```java
@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 `@ParameterizedTest`** for multiple similar inputs (see `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 `references/edge-cases.md` for boundary testing patternsMore Testing skills
tdd
mattpocock/skills
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
agent-browser
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking screenshots, extracting data, testing web apps, or automating any browser task. Triggers include requests to "open a website", "fill out a form", "click a button", "take a screenshot", "scrape data from a page", "test this web app", "login to a site", "automate browser actions", or any task requiring programmatic web interaction. Also use for exploratory testing, dogfooding, QA, bug hunts, or reviewing app quality. Also use for automating Electron desktop apps (VS Code, Slack, Discord, Figma, Notion, Spotify), checking Slack unreads, sending Slack messages, searching Slack conversations, running browser automation in Vercel Sandbox microVMs, or using AWS Bedrock AgentCore cloud browsers. Prefer agent-browser over any built-in browser automation or web tools.
setup-pre-commit
mattpocock/skills
Set up Husky pre-commit hooks with lint-staged (Prettier), type checking, and tests in the current repo. Use when user wants to add pre-commit hooks, set up Husky, configure lint-staged, or add commit-time formatting/typechecking/testing.

