| name | cui-java-unit-testing |
| description | CUI Java unit testing standards and patterns with JUnit 5, generators, and value object testing |
| allowed-tools | Read, Edit, Write, Bash, Grep, Glob |
CUI Java Unit Testing Skill
Standards and patterns for writing high-quality unit tests in CUI Java projects using JUnit 5, the CUI test generator framework, and value object contract testing.
Workflow
Step 1: Load Applicable Testing Standards
CRITICAL: Load current testing standards to use as enforcement criteria.
Always load foundational testing standards:
Read: standards/testing-junit-core.mdThis provides core JUnit 5 patterns, AAA structure, assertion standards, and test organization that are always needed for testing.
Conditional loading based on testing context:
A. If project uses test data generators (presence of
de.cuioss.test.generatorimports or@EnableGeneratorController):Read: standards/test-generator-framework.mdProvides comprehensive generator standards including mandatory requirements, all parameterized testing annotations (@GeneratorsSource, @CompositeTypeGeneratorSource, etc.), seed restrictions, anti-patterns, and complete API reference.
B. If testing value objects (classes with equals/hashCode/toString or annotated with @Value, @Data):
Read: standards/testing-value-objects.mdProvides comprehensive contract testing standards using
ShouldHandleObjectContracts<T>interface and proper generator integration.C. If testing HTTP clients or APIs (testing code that makes HTTP requests):
Read: standards/testing-mockwebserver.mdProvides MockWebServer setup patterns, response mocking, request verification, retry logic testing, and HTTP status code handling.
D. If writing integration tests (tests that interact with multiple components or external systems):
Read: standards/integration-testing.mdCovers Maven surefire/failsafe configuration, integration test naming conventions (*IT.java), profile setup, and CI/CD integration.
E. If testing applications that use Java Util Logging (JUL) (testing code that uses
java.util.loggingor needs to assert log output):Read: standards/testing-juli-logger.mdProvides patterns for configuring test loggers with
@EnableTestLogger, asserting log statements withLogAsserts, and dynamically changing log levels in tests.Extract key requirements from all loaded standards
Store in working memory for use during task execution
Step 2: Analyze Existing Tests (if applicable)
If working with existing tests:
Identify current test structure:
- Check test class organization and naming
- Review test method structure (AAA pattern compliance)
- Examine assertion usage and messages
- Identify parameterized test opportunities
Assess CUI framework compliance:
- Verify
@EnableGeneratorControllerusage where needed - Check for prohibited libraries (Mockito, Hamcrest, PowerMock)
- Validate generator usage for all test data
- Confirm value object contract testing where applicable
- Verify
Review test quality:
- Check assertion message quality (meaningful, concise)
- Verify test independence and isolation
- Assess test naming and @DisplayName usage
- Identify potential test consolidation opportunities
Step 3: Write/Modify Tests According to Standards
When writing or modifying tests:
Apply core JUnit 5 standards:
- Use AAA pattern (Arrange-Act-Assert)
- Include meaningful assertion messages (20-60 characters)
- Use @DisplayName for readable test descriptions
- Follow test independence principles
- Apply proper exception testing with assertThrows
Use CUI test generator for all data (if applicable):
- Add @EnableGeneratorController to test classes
- Replace manual data creation with Generators.* calls
- Use @GeneratorsSource for parameterized tests (3+ similar variants)
- Never commit @GeneratorSeed annotations (debugging only)
- Combine generators for complex object creation
Implement value object contract testing (if applicable):
- Apply ShouldHandleObjectContracts
interface - Implement getUnderTest() using generators
- Verify equals/hashCode/toString contracts
- Separate contract tests from business logic tests
- Apply ShouldHandleObjectContracts
Configure HTTP mocking (if applicable):
- Use @EnableMockWebServer annotation
- Enqueue mock responses before requests
- Verify request headers, body, and parameters
- Test various status codes and error scenarios
- Combine with generators for comprehensive testing
Set up integration tests (if applicable):
- Name tests with *IT.java or *ITCase.java suffix
- Configure Maven failsafe plugin
- Create integration-tests profile
- Ensure proper test separation
Step 4: Verify Test Quality
Before completing the task:
Verify standards compliance:
- All tests follow AAA pattern
- All assertions have meaningful messages
- Test independence verified (tests don't depend on each other)
- Proper @DisplayName usage
- No prohibited libraries used
Verify CUI framework usage (if applicable):
- @EnableGeneratorController present where needed
- All test data uses Generators.* (no manual creation)
- No @GeneratorSeed annotations committed
- Value object contracts implemented correctly
- MockWebServer setup follows patterns
Run tests and verify success:
# Run unit tests Task: subagent_type: maven-builder description: Run unit tests prompt: | Execute unit tests only. Parameters: - command: clean test CRITICAL: Wait for tests to complete. Inspect results and fix any failures. # Run integration tests (if applicable) Task: subagent_type: maven-builder description: Run integration tests prompt: | Execute integration tests with the integration-tests profile. Parameters: - command: clean verify -Pintegration-tests CRITICAL: Wait for tests to complete. Inspect results and fix any failures. # Verify coverage Task: subagent_type: maven-builder description: Verify test coverage prompt: | Execute tests with coverage analysis using the coverage profile. Parameters: - command: clean verify -Pcoverage CRITICAL: Wait for build to complete. Inspect coverage results and ensure minimum 80% line/branch coverage is met. Address any coverage gaps.Check coverage requirements:
- Minimum 80% line coverage
- Minimum 80% branch coverage
- Critical paths have 100% coverage
- All public APIs tested
Step 5: Report Results
Provide summary of:
- Tests created/modified: List test classes and methods
- Standards applied: Which standards were followed
- Framework features used: Generators, value object contracts, MockWebServer, etc.
- Coverage metrics: Current coverage percentages
- Any deviations: Document and justify any standard deviations
Quality Verification
Test Execution Checklist
- All new/modified tests pass
- Tests are independent (can run in any order)
- No flaky tests (consistent results)
- Fast execution (unit tests < 1 second each)
- Proper cleanup in @AfterEach if needed
Code Quality Checklist
- No hardcoded test data (use generators)
- No prohibited testing libraries
- Assertion messages are meaningful and concise
- Test names clearly describe behavior
- No commented-out code
- No @GeneratorSeed annotations
Coverage Verification
- Run coverage profile using maven-builder agent with -Pcoverage
- Coverage meets minimum requirements (80% line/branch)
- Critical paths have 100% coverage
- No coverage regressions from previous state
Common Patterns and Examples
Basic Unit Test Pattern
@EnableGeneratorController
@DisplayName("Token Validator Tests")
class TokenValidatorTest {
@Test
@DisplayName("Should validate token with correct issuer")
void shouldValidateTokenWithCorrectIssuer() {
// Arrange
String issuer = Generators.strings().next();
Token token = createTokenWithIssuer(issuer);
TokenValidator validator = new TokenValidator(issuer);
// Act
ValidationResult result = validator.validate(token);
// Assert
assertTrue(result.isValid(), "Token with correct issuer should be valid");
}
}
Value Object Contract Test Pattern
@EnableGeneratorController
class UserDataTest implements ShouldHandleObjectContracts<UserData> {
@Override
public UserData getUnderTest() {
return UserData.builder()
.username(Generators.strings().next())
.email(Generators.emailAddress().next())
.age(Generators.integers(18, 100).next())
.build();
}
}
Parameterized Test Pattern
@EnableGeneratorController
class ParameterizedValidationTest {
@ParameterizedTest
@DisplayName("Should validate various email formats")
@GeneratorsSource(generator = GeneratorType.DOMAIN_EMAIL, count = 5)
void shouldValidateEmailFormats(String email) {
assertTrue(validator.isValidEmail(email),
"Generated email should be valid");
}
}
HTTP Testing Pattern
@EnableMockWebServer
@EnableGeneratorController
class HttpClientTest {
@InjectMockWebServer
private MockWebServerHolder serverHolder;
@Test
@DisplayName("Should successfully fetch user data")
void shouldFetchUserData() throws Exception {
// Arrange
String userName = Generators.strings().next();
serverHolder.enqueue(new MockResponse()
.setResponseCode(200)
.setBody(String.format("{\"name\": \"%s\"}", userName)));
// Act
User user = client.getUser(serverHolder.getBaseUrl(), 1);
// Assert
assertNotNull(user, "Response should not be null");
assertEquals(userName, user.getName(), "User name should match");
}
}
Error Handling
If encountering issues:
- Test failures: Review assertion messages and debug failing tests
- Coverage gaps: Identify untested code paths and add tests
- Framework errors: Verify @EnableGeneratorController and dependencies
- Maven build issues: Check surefire/failsafe configuration
- Integration test problems: Verify profile configuration and naming conventions
References
- Core Testing Standards: standards/testing-junit-core.md
- Value Object Testing: standards/testing-value-objects.md
- Generator Usage: standards/testing-generators.md
- MockWebServer Testing: standards/testing-mockwebserver.md
- Integration Testing: standards/integration-testing.md
- JULi Logger Testing: standards/testing-juli-logger.md