Extend class Generator
to create a generator for a type. So that junit-quickcheck can instantiate your generator, ensure that it has a public
zero-arg constructor:
import java.awt.Dimension; public class Dimensions extends Generator<Dimension> { public Dimensions() { super(Dimension.class); } @Override public Dimension generate( SourceOfRandomness r, GenerationStatus status) { // ... } }
To generate random values for property parameters of other types, or to override the default means of generation for a supported type, mark the property parameter with @From
and supply the class of the Generator
to be used. If you give multiple @From
annotations, junit-quickcheck will choose one on every generation with probability in proportion to its frequency
attribute (default is 1).
import java.util.UUID; public class Version5 extends Generator<UUID> { public Version5() { super(UUID.class); } @Override public UUID generate( SourceOfRandomness r, GenerationStatus status) { // ... } } @RunWith(JUnitQuickcheck.class) public class IdentificationProperties { @Property public void shouldHold(@From(Version5.class) UUID u) { // ... } }
junit-quickcheck has built-in facilities for generating values for types that are functional interfaces (whether or not they are marked with [FunctionalInterface] (http://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html), arrays, or enum
s. Explicitly naming generators for parameters of these types overrides the built-in means of generation. This is usually necessary for functional interfaces that involve generics.
If the generator is in the same package as the class you’re generating and it has the same name with an additional Gen
suffix, then it should be found automatically.
ServiceLoader
To use a generator for your own type without having to use @From
, you can arrange for a [ServiceLoader] (http://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) to discover it.
META-INF/services
, called com.pholser.junit.quickcheck.generator.Generator
.Ensure your generator class and the provider configuration file are on the class path. junit-quickcheck will make generators packaged in this way available for use.
The generators in the module junit-quickcheck-generators
are loaded via this mechanism also. Any generators you supply and make available to the ServiceLoader
complement these generators rather than override them.
Ctor
You can generate values for a type that has a single accessible constructor by using the Ctor
generator with @From
.
public class DollarsAndCents { private final BigDecimal amount; public DollarsAndCents(BigDecimal amount) { this.amount = amount.setScale(2, BigDecimal.ROUND_HALF_EVEN); } // ... } @RunWith(JUnitQuickcheck.class) public class DollarsAndCentsProperties { @Property public void rounding(@From(Ctor.class) DollarsAndCents d) { // ... } }
junit-quickcheck will find generators appropriate for the types of the constructor parameters, and call upon them to supply values to the constructor invocation. Any configuration annotations on the constructor parameters will be honored.
Fields
You can generate values for a type that has an accessible zero-arg constructor by using the Fields
generator with @From
.
public class Counter { private int count; public Counter increment() { ++count; return this; } public Counter decrement() { --count; return this; } public int count() { return count; } } @RunWith(JUnitQuickcheck.class) public class CounterProperties { @Property public void incrementing(@From(Fields.class) Counter c) { int count = c.count(); assertEquals(count + 1, c.increment().count()); } @Property public void decrementing(@From(Fields.class) Counter c) { int count = c.count(); assertEquals(count - 1, c.decrement().count()); } }
junit-quickcheck will find generators appropriate for the types of the fields of the class, and call upon them to supply values to the fields of a new instance of the class (subverting access protection). Any configuration annotations on the fields will be honored.