package io.dropwizard.validation;

import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.jersey.validation.MutableValidatorFactory;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import org.hibernate.validator.internal.constraintvalidators.bv.number.bound.MinValidatorForInteger;
import org.hibernate.validator.internal.engine.constraintvalidation.ConstraintValidatorFactoryImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import javax.validation.ConstraintValidatorFactory;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.constraints.Min;
import java.util.Optional;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.AdditionalAnswers.delegatesTo;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

class InjectValidatorFeatureTest {

    private final Application<Configuration> application = new Application<Configuration>() {
        @Override
        public void initialize(Bootstrap<Configuration> bootstrap) { }

        @Override
        public void run(Configuration configuration, Environment environment) { }
    };

    private ValidatorFactory validatorFactory;

    @BeforeEach
    void setUp() throws Exception {
        Bootstrap<Configuration> bootstrap = new Bootstrap<>(application);
        application.initialize(bootstrap);

        validatorFactory = bootstrap.getValidatorFactory();
    }

    @Test
    void shouldReplaceValidatorFactory() {
        ConstraintValidatorFactory factory = validatorFactory.getConstraintValidatorFactory();

        assertThat(factory).isInstanceOf(MutableValidatorFactory.class);
    }

    @Test
    void shouldValidateNormally() {
        Validator validator = validatorFactory.getValidator();

        // Run validation manually
        Set<ConstraintViolation<Bean>> constraintViolations = validator.validate(new Bean(1));


        assertThat(constraintViolations.size()).isEqualTo(1);

        Optional<String> message = constraintViolations.stream()
            .findFirst()
            .map(ConstraintViolation::getMessage);

        assertThat(message).hasValue("must be greater than or equal to 10");
    }

    @Test
    void shouldInvokeUpdatedFactory() {
        MutableValidatorFactory mutableFactory = (MutableValidatorFactory) validatorFactory
            .getConstraintValidatorFactory();

        ConstraintValidatorFactory mockedFactory = mock(
            ConstraintValidatorFactory.class,
            delegatesTo(new ConstraintValidatorFactoryImpl())
        );

        // Swap validator factory at runtime
        mutableFactory.setValidatorFactory(mockedFactory);

        // Run validation manually
        Validator validator = validatorFactory.getValidator();
        validator.validate(new Bean(1));

        verify(mockedFactory).getInstance(MinValidatorForInteger.class);
    }

    static class Bean {

        @Min(10)
        final int value;

        Bean(int value) {
            this.value = value;
        }
    }
}

@@ -1393,25 +1393,8 @@
 Up()
- throws Exception
  %7B%0A 
@@ -2048,17 +2048,16 @@
 n(1));%0A%0A
-%0A
         
@@ -2091,118 +2091,35 @@
 ions
-.size()).isEqualTo(1);%0A%0A        Optional%3CString%3E message = constraintViolations.stream()%0A            .findFirs
+)%0A            .singleElemen
 t()%0A
@@ -2135,11 +2135,18 @@
    .
-map
+extracting
 (Con
@@ -2174,18 +2174,16 @@
 Message)
-;%0A
 %0A       
@@ -2187,36 +2187,22 @@
     
-assertThat(message).hasValue
+    .isEqualTo
 (%22mu

Simplify InjectValidatorFeatureTest