CtrlK
BlogDocsLog inGet started
Tessl Logo

giuseppe-trisciuoglio/developer-kit

Comprehensive developer toolkit providing reusable skills for Java/Spring Boot, TypeScript/NestJS/React/Next.js, Python, PHP, AWS CloudFormation, AI/RAG, DevOps, and more.

90

Quality

90%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Risky

Do not use without reviewing

This version of the tile failed moderation
Moderation pipeline encountered an internal error
Overview
Quality
Evals
Security
Files

custom-validators.mdplugins/developer-kit-java/skills/unit-test-bean-validation/references/

Custom Validators Testing Reference

Creating Custom Constraints

Annotation Definition

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneNumberValidator.class)
public @interface ValidPhoneNumber {
  String message() default "invalid phone number format";
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
}

Validator Implementation

public class PhoneNumberValidator implements ConstraintValidator<ValidPhoneNumber, String> {
  private static final String PHONE_PATTERN = "^\\d{3}-\\d{3}-\\d{4}$";

  @Override
  public boolean isValid(String value, ConstraintValidatorContext context) {
    if (value == null) return true; // null handled by @NotNull
    return value.matches(PHONE_PATTERN);
  }
}

Unit Test

class PhoneNumberValidatorTest extends BaseValidationTest {

  @Test
  void shouldAcceptValidPhoneNumber() {
    Contact contact = new Contact("Alice", "555-123-4567");
    assertThat(validator.validate(contact)).isEmpty();
  }

  @Test
  void shouldRejectInvalidFormat() {
    Contact contact = new Contact("Alice", "5551234567");
    assertThat(validator.validate(contact))
      .extracting(ConstraintViolation::getMessage)
      .contains("invalid phone number format");
  }

  @Test
  void shouldAllowNull() {
    Contact contact = new Contact("Alice", null);
    assertThat(validator.validate(contact)).isEmpty();
  }
}

Cross-Field Validation

Password Match Example

@PasswordsMatch
public class ChangePasswordRequest {
  private String newPassword;
  private String confirmPassword;
}

@Constraint(validatedBy = PasswordMatchValidator.class)
public @interface PasswordsMatch {
  String message() default "passwords do not match";
  Class<?>[] groups() default {};
}

public class PasswordMatchValidator
    implements ConstraintValidator<PasswordsMatch, ChangePasswordRequest> {
  @Override
  public boolean isValid(ChangePasswordRequest value, ConstraintValidatorContext context) {
    if (value == null) return true;
    return value.getNewPassword().equals(value.getConfirmPassword());
  }
}

Test

class PasswordValidationTest extends BaseValidationTest {

  @Test
  void shouldPassWhenPasswordsMatch() {
    var request = new ChangePasswordRequest("pass123", "pass123");
    assertThat(validator.validate(request)).isEmpty();
  }

  @Test
  void shouldFailWhenPasswordsDoNotMatch() {
    var request = new ChangePasswordRequest("pass123", "different");
    assertThat(validator.validate(request))
      .extracting(ConstraintViolation::getMessage)
      .contains("passwords do not match");
  }
}

Best Practices

  • Keep validators stateless - no instance fields
  • Return true for null values - let @NotNull handle null checks
  • Provide clear error messages in annotations
  • Test both valid and invalid cases
  • Verify property path and message in assertions

plugins

developer-kit-java

skills

unit-test-bean-validation

README.md

CHANGELOG.md

context7.json

CONTRIBUTING.md

README_CN.md

README_ES.md

README_IT.md

README.md

tessl.json

tile.json