跳到主要内容
知仓学习社ZHICANG

unit-test-utility-methods

Provides patterns for testing utility classes, static methods, and helper functions. Validates pure functions, null handling, edge cases, and bounda…

不碰外部(只输出文字)无严重或高危命中giuseppe-trisciuoglio/developer-kit

它会碰到什么

扫了多少3 个文本文件,12 KB
它会碰到什么不碰外部(只输出文字)
命中总数0 处
命中统计严重 0 · 高 0 · 中 0 · 低 0

这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。

技能内容

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

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 @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 patterns

想直接用这个技能?

本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。