Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>it.aboutbits</groupId>
<artifactId>spring-boot-testing</artifactId>
<version>BUILD-SNAPSHOT</version>
Expand All @@ -13,7 +20,29 @@
</properties>

<dependencies>
<dependency>
<groupId>it.aboutbits</groupId>
<artifactId>spring-boot-toolbox</artifactId>
<version>1.0.0-RC1</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

<!-- Utilities -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!-- Testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package it.aboutbits.springboot.testing.validation.core;

import it.aboutbits.springboot.testing.validation.rule.BetweenRule;
import it.aboutbits.springboot.testing.validation.rule.FutureRule;
import it.aboutbits.springboot.testing.validation.rule.MaxRule;
import it.aboutbits.springboot.testing.validation.rule.MinRule;
import it.aboutbits.springboot.testing.validation.rule.NegativeOrZeroRule;
import it.aboutbits.springboot.testing.validation.rule.NegativeRule;
import it.aboutbits.springboot.testing.validation.rule.NotBlankRule;
import it.aboutbits.springboot.testing.validation.rule.NotEmptyRule;
import it.aboutbits.springboot.testing.validation.rule.NotNullRule;
import it.aboutbits.springboot.testing.validation.rule.NotValidatedRule;
import it.aboutbits.springboot.testing.validation.rule.NullableRule;
import it.aboutbits.springboot.testing.validation.rule.PastRule;
import it.aboutbits.springboot.testing.validation.rule.PositiveOrZeroRule;
import it.aboutbits.springboot.testing.validation.rule.PositiveRule;
import it.aboutbits.springboot.testing.validation.rule.ValidBeanRule;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

import java.util.ArrayList;
import java.util.List;

@RequiredArgsConstructor
public abstract class BaseRuleBuilder<R extends BaseRuleBuilder<?>> implements
ValidationRulesData,
BetweenRule<R>,
FutureRule<R>,
MaxRule<R>,
MinRule<R>,
NegativeOrZeroRule<R>,
NegativeRule<R>,
NotBlankRule<R>,
NotEmptyRule<R>,
NotNullRule<R>,
NullableRule<R>,
PastRule<R>,
PositiveOrZeroRule<R>,
PositiveRule<R>,
NotValidatedRule<R>,
ValidBeanRule<R> {
@Getter(AccessLevel.PACKAGE)
private final List<Rule> rules = new ArrayList<>();

@Setter(AccessLevel.PACKAGE)
private Runnable triggerValidation;

@Override
public void addRule(@NonNull Rule rule) {
rules.add(rule);
}

public void isCompliant() {
triggerValidation.run();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package it.aboutbits.springboot.testing.validation.core;

import it.aboutbits.springboot.toolbox.type.CustomType;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

import java.util.HashSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class BaseValidationAssert<R extends BaseRuleBuilder<?>> {
@Getter(AccessLevel.PROTECTED)
private final R ruleBuilder;

protected static final Set<Class<?>> NON_BEAN_TYPES = new HashSet<>(
Set.of(
CustomType.class
)
);
Comment thread
mmalfertheiner marked this conversation as resolved.

private Object parameterUnderTest;

@Setter(AccessLevel.PRIVATE)
private Consumer<?> functionToCallWithParameter = null;

public static void registerNonBeanType(Class<?> type) {
NON_BEAN_TYPES.add(type);
}

public <P> CallBuilder<R, P> of(@NonNull P parameterUnderTest) {
this.parameterUnderTest = parameterUnderTest;
ruleBuilder.setTriggerValidation(this::assertValidation);
return new CallBuilder<>(this);
}

@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public static final class CallBuilder<R extends BaseRuleBuilder<?>, P> {
private final BaseValidationAssert<R> parent;

public R calling(@NonNull Consumer<P> functionToCallWithParameter) {
parent.setFunctionToCallWithParameter(functionToCallWithParameter);
return parent.ruleBuilder;
}

public R usingBeanValidation() {
return parent.ruleBuilder;
}

@SuppressWarnings("unchecked")
public <ID> R calling(
@NonNull BiConsumer<ID, P> functionToCallWithParameter,
@NonNull ID id
) {
parent.setFunctionToCallWithParameter(
p -> functionToCallWithParameter.accept(id, (P) p)
);
return parent.ruleBuilder;
}
}

private void assertValidation() {
new RuleValidator<>().assertValidation(
new RuleValidator.AssertionParameter<>(
parameterUnderTest,
functionToCallWithParameter,
ruleBuilder.getRules(),
NON_BEAN_TYPES
)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package it.aboutbits.springboot.testing.validation.core;

import it.aboutbits.springboot.testing.validation.source.InertValueSource;
import lombok.AccessLevel;
import lombok.Getter;

public final class Rule {
@Getter(AccessLevel.PACKAGE)
private final String property;

@Getter(AccessLevel.PACKAGE)
private final Class<? extends ValueSource> valueSource;

@Getter(AccessLevel.PACKAGE)
private final Object[] args;

@Getter(AccessLevel.PACKAGE)
private boolean requireValid = false;

@Getter(AccessLevel.PACKAGE)
private boolean requireNullable = false;

public Rule(String property, Class<? extends ValueSource> valueSource, Object... args) {
checkPropertyName(property);

this.property = property;
this.valueSource = valueSource;
this.args = args;
}

public static Rule validAnnotated(String property) {
checkPropertyName(property);

var rule = new Rule(property, InertValueSource.class);
rule.requireValid = true;
return rule;
}

public static Rule nullableAnnotated(String property) {
checkPropertyName(property);

var rule = new Rule(property, InertValueSource.class);
rule.requireNullable = true;
return rule;
}

private static void checkPropertyName(String property) {
if (property.contains(".")) {
throw new IllegalArgumentException("Referencing sub-objects using dot notation is not supported.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package it.aboutbits.springboot.testing.validation.core;

class RuleValidationException extends RuntimeException {
RuleValidationException(String message) {
super(message);
}

RuleValidationException(String message, Throwable cause) {
super(message, cause);
}
}
Loading