A fluent API for enforcing design contracts with automatic message generation:
✔️ Easy to use
✔️ Fast
✔️ Production-ready
To get started, add this Maven dependency:
<dependency>
<groupId>com.github.cowwoc.requirements</groupId>
<artifactId>java</artifactId>
<version>10.0</version>
</dependency>
import java.util.List;
import java.util.StringJoiner;
import static com.github.cowwoc.requirements10.java.DefaultJavaValidators.checkIf;
import static com.github.cowwoc.requirements10.java.DefaultJavaValidators.requireThat;
import static com.github.cowwoc.requirements10.java.DefaultJavaValidators.that;
public final class Cake
{
private byte bitesTaken = 0;
private int piecesLeft;
public Cake(int piecesLeft)
{
requireThat(piecesLeft, "piecesLeft").isPositive();
this.piecesLeft = piecesLeft;
}
public int eat()
{
++bitesTaken;
assert that(bitesTaken, "bitesTaken").isNotNegative().elseThrow();
piecesLeft -= ThreadLocalRandom.current().nextInt(5);
assert that(piecesLeft, "piecesLeft").isNotNegative().elseThrow();
return piecesLeft;
}
public List<String> getFailures()
{
return checkIf(bitesTaken, "bitesTaken").isNotNegative().
and(checkIf(piecesLeft, "piecesLeft").isGreaterThan(3)).
elseGetMessages();
}
}
If you violate a precondition:
Cake cake = new Cake(-1000);
You'll get:
java.lang.IllegalArgumentException: "piecesLeft" must be positive.
actual: -1000
If you violate a class invariant:
Cake cake = new Cake(1_000_000);
while (true)
cake.eat();
You'll get:
java.lang.AssertionError: "bitesTaken" may not be negative.
actual: -128
If you violate a postcondition:
Cake cake = new Cake(100);
while (true)
cake.eat();
You'll get:
java.lang.AssertionError: "piecesLeft" may not be negative.
actual: -4
If you violate multiple conditions at once:
Cake cake = new Cake(1);
cake.bitesTaken = -1;
cake.piecesLeft = 2;
StringJoiner failures = new StringJoiner("\n\n");
for (String failure : cake.getFailures())
failures.add(failure);
System.out.println(failures);
You'll get:
"bitesTaken" may not be negative.
actual: -1
"piecesLeft" must be greater than 3.
actual: 2
This library offers the following features:
- Automatic message generation for validation failures
- Diffs provided whenever possible to highlight the differences between expected and actual values
- Clean stack-traces that remove unnecessary frames
- Zero overhead when assertions are disabled for better performance
- Multiple validation failures that report all the errors at once
- Nested validations that allow you to validate complex objects
- String diff that shows the differences between two strings
- Performant and robust
Designed for discovery using your favorite IDE's auto-complete feature. The main entry points are:
- requireThat(value, name) for method preconditions.
- that(value, name) for class invariants, method postconditions and private methods.
- checkIf(value, name) for multiple failures and customized error handling.
See the API documentation for more details.
- Use
checkIf().elseGetMessages()
to return failure messages without throwing an exception. This is the fastest validation approach, ideal for web services. - To enhance the clarity of failure messages, you should provide parameter names, even when they are optional.
In other words, favor
assert that(value, name)
overassert that(value)
.
This library supports the following third-party libraries and tools:
- This library is licensed under the Apache License, Version 2.0
- See Third party licenses for the licenses of the dependencies
- Icons made by Flat Icons from www.flaticon.com are licensed by CC 3.0 BY