mirror of
https://github.com/fabioformosa/quartz-manager.git
synced 2026-01-05 17:13:28 +09:00
#57 added validation checks onto the SimpleTrigger
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package it.fabioformosa.quartzmanager.api.dto;
|
||||
|
||||
public interface RepetitionDTO {
|
||||
Integer getRepeatCount();
|
||||
|
||||
Long getRepeatInterval();
|
||||
|
||||
void setRepeatCount(Integer repeatCount);
|
||||
|
||||
void setRepeatInterval(Long repeatInterval);
|
||||
}
|
||||
@@ -1,21 +1,19 @@
|
||||
package it.fabioformosa.quartzmanager.api.dto;
|
||||
|
||||
import it.fabioformosa.quartzmanager.api.validators.ValidRepetition;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
public class SimpleTriggerInputDTO extends TriggerCommandDTO {
|
||||
@ValidRepetition
|
||||
public class SimpleTriggerInputDTO extends TriggerCommandDTO implements RepetitionDTO {
|
||||
|
||||
@NotNull
|
||||
private Integer repeatCount;
|
||||
|
||||
@NotNull
|
||||
private Long repeatInterval;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.Date;
|
||||
|
||||
@SuperBuilder
|
||||
@@ -15,7 +15,7 @@ import java.util.Date;
|
||||
@Data
|
||||
public class TriggerCommandDTO {
|
||||
|
||||
@NotNull
|
||||
@NotBlank
|
||||
private String jobClass;
|
||||
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package it.fabioformosa.quartzmanager.api.validators;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Constraint(validatedBy = ValidRepetitionValidator.class)
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ValidRepetition {
|
||||
|
||||
String message() default "Invalid repetition values";
|
||||
Class<?>[] groups() default {};
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package it.fabioformosa.quartzmanager.api.validators;
|
||||
|
||||
import it.fabioformosa.quartzmanager.api.dto.RepetitionDTO;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
public class ValidRepetitionValidator implements ConstraintValidator<ValidRepetition, RepetitionDTO> {
|
||||
|
||||
@Override
|
||||
public boolean isValid(RepetitionDTO repetitionDTO, ConstraintValidatorContext constraintValidatorContext) {
|
||||
return (repetitionDTO.getRepeatCount() == null && repetitionDTO.getRepeatInterval() == null) ||
|
||||
(repetitionDTO.getRepeatCount() != null && repetitionDTO.getRepeatInterval() != null);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
package it.fabioformosa.quartzmanager.api.controllers;
|
||||
|
||||
import it.fabioformosa.quartzmanager.api.QuartManagerApplicationTests;
|
||||
import it.fabioformosa.quartzmanager.api.controllers.utils.InvalidSimpleTriggerCommandDTOProvider;
|
||||
import it.fabioformosa.quartzmanager.api.common.utils.DateUtils;
|
||||
import it.fabioformosa.quartzmanager.api.controllers.utils.TestUtils;
|
||||
import it.fabioformosa.quartzmanager.api.controllers.utils.TriggerUtils;
|
||||
import it.fabioformosa.quartzmanager.api.dto.MisfireInstruction;
|
||||
import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerCommandDTO;
|
||||
import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerDTO;
|
||||
import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerInputDTO;
|
||||
import it.fabioformosa.quartzmanager.api.services.SimpleTriggerService;
|
||||
import it.fabioformosa.quartzmanager.api.exceptions.TriggerNotFoundException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
@@ -55,16 +53,8 @@ class SimpleTriggerControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenAnExistingTrigger_whenGetIsCalled_then404IsReturned() throws Exception {
|
||||
Mockito.when(simpleTriggerService.getSimpleTriggerByName("not_existing_trigger_name")).thenThrow(new TriggerNotFoundException("not_existing_trigger_name"));
|
||||
|
||||
mockMvc.perform(get(SimpleTriggerController.SIMPLE_TRIGGER_CONTROLLER_BASE_URL + "/not_existing_trigger_name")
|
||||
.contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenASimpleTriggerCommandDTO_whenPosted_thenANewSimpleTriggerIsCreated() throws Exception {
|
||||
SimpleTriggerInputDTO simpleTriggerInputDTO = buildSimpleTriggerCommandDTO();
|
||||
void givenACompleteSimpleTriggerCommandDTO_whenPosted_thenANewSimpleTriggerIsCreated() throws Exception {
|
||||
SimpleTriggerInputDTO simpleTriggerInputDTO = buildACompleteSimpleTriggerCommandDTO();
|
||||
SimpleTriggerDTO expectedSimpleTriggerDTO = TriggerUtils.getSimpleTriggerInstance("mytrigger", simpleTriggerInputDTO);
|
||||
Mockito.when(simpleTriggerService.scheduleSimpleTrigger(any())).thenReturn(expectedSimpleTriggerDTO);
|
||||
mockMvc.perform(
|
||||
@@ -77,27 +67,20 @@ class SimpleTriggerControllerTest {
|
||||
;
|
||||
}
|
||||
|
||||
private SimpleTriggerInputDTO buildSimpleTriggerCommandDTO() {
|
||||
private SimpleTriggerInputDTO buildACompleteSimpleTriggerCommandDTO() {
|
||||
return SimpleTriggerInputDTO.builder()
|
||||
.jobClass("it.fabioformosa.quartzmanager.api.jobs.SampleJob")
|
||||
.startDate(new Date())
|
||||
.repeatCount(20)
|
||||
.repeatInterval(20000L)
|
||||
.endDate(DateUtils.addHoursToNow(6))
|
||||
.misfireInstruction(MisfireInstruction.MISFIRE_INSTRUCTION_FIRE_NOW)
|
||||
.repeatCount(5)
|
||||
.repeatInterval(1000L * 60 * 60)
|
||||
.build();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(InvalidSimpleTriggerCommandDTOProvider.class)
|
||||
void givenAnInvalidSimpleTriggerCommandDTO_whenPostedANewTrigger_thenAnErrorIsReturned(SimpleTriggerInputDTO invalidSimpleTriggerComandDTO) throws Exception {
|
||||
mockMvc.perform(post(SimpleTriggerController.SIMPLE_TRIGGER_CONTROLLER_BASE_URL + "/mytrigger")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(TestUtils.toJson(invalidSimpleTriggerComandDTO)))
|
||||
.andExpect(MockMvcResultMatchers.status().is4xxClientError());
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenATriggerName_whenPutSimpleTriggerCommandDTO_thenTheSimpleTriggerIsRescheduled() throws Exception {
|
||||
SimpleTriggerInputDTO simpleTriggerInputDTO = buildSimpleTriggerCommandDTO();
|
||||
SimpleTriggerInputDTO simpleTriggerInputDTO = buildACompleteSimpleTriggerCommandDTO();
|
||||
SimpleTriggerDTO expectedSimpleTriggerDTO = TriggerUtils.getSimpleTriggerInstance("mytrigger", simpleTriggerInputDTO);
|
||||
SimpleTriggerCommandDTO simpleTriggerCommandDTO = SimpleTriggerCommandDTO.builder()
|
||||
.triggerName("mytrigger")
|
||||
@@ -112,13 +95,4 @@ class SimpleTriggerControllerTest {
|
||||
.andExpect(MockMvcResultMatchers.content().json(TestUtils.toJson(expectedSimpleTriggerDTO)));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(InvalidSimpleTriggerCommandDTOProvider.class)
|
||||
void givenAnInvalidSimpleTriggerCommandDTO_whenATriggerIsRescheduled_thenAnErrorIsReturned(SimpleTriggerInputDTO invalidSimpleTriggerCommandTO) throws Exception {
|
||||
mockMvc.perform(put(SimpleTriggerController.SIMPLE_TRIGGER_CONTROLLER_BASE_URL + "/mytrigger")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(TestUtils.toJson(invalidSimpleTriggerCommandTO)))
|
||||
.andExpect(MockMvcResultMatchers.status().is4xxClientError());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package it.fabioformosa.quartzmanager.api.controllers;
|
||||
|
||||
import it.fabioformosa.quartzmanager.api.QuartManagerApplicationTests;
|
||||
import it.fabioformosa.quartzmanager.api.controllers.utils.InvalidSimpleTriggerCommandDTOProvider;
|
||||
import it.fabioformosa.quartzmanager.api.controllers.utils.TestUtils;
|
||||
import it.fabioformosa.quartzmanager.api.controllers.utils.TriggerUtils;
|
||||
import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerDTO;
|
||||
import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerInputDTO;
|
||||
import it.fabioformosa.quartzmanager.api.exceptions.TriggerNotFoundException;
|
||||
import it.fabioformosa.quartzmanager.api.services.SimpleTriggerService;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ArgumentsSource;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
|
||||
@ContextConfiguration(classes = {QuartManagerApplicationTests.class})
|
||||
@WebMvcTest(controllers = SimpleTriggerController.class, properties = {
|
||||
"quartz-manager.jobClassPackages=it.fabioformosa.quartzmanager.jobs"
|
||||
})
|
||||
class SimpleTriggerControllerValidationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@MockBean
|
||||
private SimpleTriggerService simpleTriggerService;
|
||||
|
||||
@AfterEach
|
||||
void cleanUp(){
|
||||
Mockito.reset(simpleTriggerService);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void givenANotExistingTrigger_whenGetIsCalled_then404IsReturned() throws Exception {
|
||||
Mockito.when(simpleTriggerService.getSimpleTriggerByName("not_existing_trigger_name")).thenThrow(new TriggerNotFoundException("not_existing_trigger_name"));
|
||||
|
||||
mockMvc.perform(get(SimpleTriggerController.SIMPLE_TRIGGER_CONTROLLER_BASE_URL + "/not_existing_trigger_name")
|
||||
.contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.status().isNotFound());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void givenAMinimalSimpleTriggerCommandDTO_whenPosted_thenANewSimpleTriggerIsCreated() throws Exception {
|
||||
SimpleTriggerInputDTO simpleTriggerInputDTO = buildAMinimalSimpleTriggerCommandDTO();
|
||||
SimpleTriggerDTO expectedSimpleTriggerDTO = TriggerUtils.getSimpleTriggerInstance("my-minimal-trigger");
|
||||
Mockito.when(simpleTriggerService.scheduleSimpleTrigger(any())).thenReturn(expectedSimpleTriggerDTO);
|
||||
mockMvc.perform(
|
||||
post(SimpleTriggerController.SIMPLE_TRIGGER_CONTROLLER_BASE_URL + "/my-minimal-trigger")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(TestUtils.toJson(simpleTriggerInputDTO))
|
||||
)
|
||||
.andExpect(MockMvcResultMatchers.status().isCreated())
|
||||
.andExpect(MockMvcResultMatchers.content().json(TestUtils.toJson(expectedSimpleTriggerDTO)))
|
||||
;
|
||||
}
|
||||
|
||||
private SimpleTriggerInputDTO buildAMinimalSimpleTriggerCommandDTO() {
|
||||
return SimpleTriggerInputDTO.builder()
|
||||
.jobClass("it.fabioformosa.quartzmanager.api.jobs.SampleJob")
|
||||
.build();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(InvalidSimpleTriggerCommandDTOProvider.class)
|
||||
void givenAnInvalidSimpleTriggerCommandDTO_whenPostedANewTrigger_thenAnErrorIsReturned(SimpleTriggerInputDTO invalidSimpleTriggerComandDTO) throws Exception {
|
||||
mockMvc.perform(post(SimpleTriggerController.SIMPLE_TRIGGER_CONTROLLER_BASE_URL + "/mytrigger")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(TestUtils.toJson(invalidSimpleTriggerComandDTO)))
|
||||
.andExpect(MockMvcResultMatchers.status().is4xxClientError());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(InvalidSimpleTriggerCommandDTOProvider.class)
|
||||
void givenAnInvalidSimpleTriggerCommandDTO_whenATriggerIsRescheduled_thenAnErrorIsReturned(SimpleTriggerInputDTO invalidSimpleTriggerCommandTO) throws Exception {
|
||||
mockMvc.perform(put(SimpleTriggerController.SIMPLE_TRIGGER_CONTROLLER_BASE_URL + "/mytrigger")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(TestUtils.toJson(invalidSimpleTriggerCommandTO)))
|
||||
.andExpect(MockMvcResultMatchers.status().is4xxClientError());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import java.util.stream.Stream;
|
||||
|
||||
public class InvalidSimpleTriggerCommandDTOProvider implements ArgumentsProvider {
|
||||
@Override
|
||||
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
|
||||
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) {
|
||||
return Stream.of(
|
||||
Arguments.of(SimpleTriggerInputDTO.builder().build()),
|
||||
Arguments.of(SimpleTriggerInputDTO.builder().repeatCount(1).build()),
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package it.fabioformosa.quartzmanager.api.validators;
|
||||
|
||||
import it.fabioformosa.quartzmanager.api.dto.RepetitionDTO;
|
||||
import it.fabioformosa.quartzmanager.api.dto.SimpleTriggerInputDTO;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
|
||||
class ValidRepetitionValidatorTest {
|
||||
|
||||
private ValidRepetitionValidator validRepetitionValidator = new ValidRepetitionValidator();
|
||||
|
||||
@Test
|
||||
public void givenACountAndIntervalSet_whenTheValidatorIsCalled_shouldReturnValid() {
|
||||
RepetitionDTO repetitionDTO = new SimpleTriggerInputDTO();
|
||||
repetitionDTO.setRepeatCount(10);
|
||||
repetitionDTO.setRepeatInterval(1000L);
|
||||
boolean valid = validRepetitionValidator.isValid(repetitionDTO, null);
|
||||
Assertions.assertThat(valid).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenACountAndIntervalUnSet_whenTheValidatorIsCalled_shouldReturnInValid() {
|
||||
RepetitionDTO repetitionDTO = new SimpleTriggerInputDTO();
|
||||
boolean valid = validRepetitionValidator.isValid(repetitionDTO, null);
|
||||
Assertions.assertThat(valid).isTrue();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource({"10, ", ",1000"})
|
||||
public void givenACountAndIntervalNotSet_whenTheValidatorIsCalled_shouldReturnInValid(String repeatCountStr, String repeatIntervalStr) {
|
||||
Integer repeatCount = null;
|
||||
if (StringUtils.isNotBlank(repeatCountStr))
|
||||
repeatCount = Integer.valueOf(repeatCountStr);
|
||||
|
||||
Long repeatInterval = null;
|
||||
if (StringUtils.isNotBlank(repeatIntervalStr))
|
||||
repeatInterval = Long.valueOf(repeatIntervalStr);
|
||||
|
||||
RepetitionDTO repetitionDTO = new SimpleTriggerInputDTO();
|
||||
repetitionDTO.setRepeatInterval(repeatInterval);
|
||||
repetitionDTO.setRepeatCount(repeatCount);
|
||||
|
||||
boolean valid = validRepetitionValidator.isValid(repetitionDTO, null);
|
||||
Assertions.assertThat(valid).isFalse();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user