Skip to content

Commit

Permalink
Add test case for validator bug reproduction
Browse files Browse the repository at this point in the history
  • Loading branch information
mancze committed Feb 26, 2024
1 parent 9783571 commit f157724
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 4 deletions.
6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ repositories {
}

dependencies {
annotationProcessor("io.micronaut.serde:micronaut-serde-processor")
annotationProcessor("io.micronaut.validation:micronaut-validation-processor")

implementation("io.micronaut.serde:micronaut-serde-jackson")
implementation("io.micronaut.validation:micronaut-validation")

runtimeOnly("ch.qos.logback:logback-classic")
runtimeOnly("org.yaml:snakeyaml:2.2")

testImplementation("io.micronaut:micronaut-http-client")
testImplementation("org.assertj:assertj-core:3.25.3")
}

java {
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/com/example/ValidatedBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.example;

import com.example.validation.ValidInternalId;
import com.example.validation.ValidatedByFactory;
import io.micronaut.core.annotation.Introspected;

@Introspected
public record ValidatedBean(
@ValidatedByFactory
String value,
@ValidInternalId
int internalId) {
}
22 changes: 22 additions & 0 deletions src/main/java/com/example/validation/ValidInternalId.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.example.validation;

import jakarta.validation.Constraint;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;

import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = {})
@Target(
{
ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.TYPE_USE
}
)
@Retention(RetentionPolicy.RUNTIME)
@NotNull
@Positive
@Max(Integer.MAX_VALUE)
public @interface ValidInternalId {
}
18 changes: 18 additions & 0 deletions src/main/java/com/example/validation/ValidatedByFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.validation;

import jakarta.validation.Constraint;
import jakarta.validation.constraints.Size;

import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = {})
@Target(
{
ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.TYPE_USE
}
)
@Retention(RetentionPolicy.RUNTIME)
@Size(max = 32)
public @interface ValidatedByFactory {
}
18 changes: 18 additions & 0 deletions src/main/java/com/example/validation/ValidatorFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.example.validation;

import io.micronaut.context.annotation.Factory;
import io.micronaut.core.annotation.Introspected;
import io.micronaut.validation.validator.constraints.ConstraintValidator;
import jakarta.inject.Singleton;

@Factory
@Introspected
public class ValidatorFactory {

@Singleton
ConstraintValidator<ValidatedByFactory, CharSequence> validatedByFactoryValidator() {
return (ignored1, ignored2, ignored3) -> true;
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import org.junit.jupiter.api.Test;

@MicronautTest
class MicronautSandboxTest {
class ApplicationTest {

@Inject
EmbeddedApplication<?> application;
Expand Down
55 changes: 55 additions & 0 deletions src/test/java/com/example/ValidatorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.example;

import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import jakarta.inject.Inject;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

@MicronautTest(rebuildContext = true, startApplication = false)
public class ValidatorTest {

@Inject
Validator validator;

@Test
void BUG_REPRODUCTION_CASE_validateValidBean_shouldNotFail() {
var bean = new ValidatedBean("foobar", 42);

assertThat(validator.validate(bean)).isEmpty();
}

@Test
void validateValidBean_workaround() {
var validBean = new ValidatedBean("foobar", 42);

warmUpValidator(validBean);

assertThat(validator.validate(validBean)).isEmpty();
}

@Test
void validateInvalidBean_shouldFail() {
var invalidBean = new ValidatedBean("foobar", -123);

warmUpValidator(invalidBean);

assertThat(validator.validate(invalidBean))
.singleElement()
.returns(-123, ConstraintViolation::getInvalidValue);
}


/**
* Workaround for the bug
*/
private void warmUpValidator(ValidatedBean validBean) {
try {
validator.validate(validBean);
} catch (Exception e) {
System.out.println(e);
}
}
}

0 comments on commit f157724

Please sign in to comment.