4

When writing a generator for junit-quickcheck, it's easy to use the Ctor or Fields reflection methods provided. But applying reflection directly on my business models prevents me from restricting the generated data (unless I interleave my business models with quickcheck annotataions).

For example:

class Price {
    public final BigDecimal price;
    public final BigDecimal discountPercentage;
    // With a constructor
}

The price field can be any (reasonable) BigDecimal (lets say up to 1000), but the discount must be between 0 and 100.

How to write a generator the idiomatic way?

My current approach is to create a class that specifies the model to be generated:

class PriceFields {
    public @InRange(max="1000") BigDecimal price;
    public @InRange(max="100") BigDecimal discountPercentage;

    public Price toPrice(){
        return new Price(price, discountPercentage);
    }
}

And a generator like this:

public class PriceGenerator extends Generator<Price> {
    public PriceGenerator() {
        super(Price.class);
    }

    @Override
    public Price generate(SourceOfRandomness random, GenerationStatus status) {
        return gen().fieldsOf(PriceFields.class)
            .generate(random, status)
            .toPrice();
    }
}

But I would like to be able to write something like this (without the PriceFields class):

public class PriceGenerator extends Generator<Price> {
    public PriceGenerator() {
        super(Price.class);
    }

    @Override
    public Price generate(SourceOfRandomness random, GenerationStatus status) {
        BigDecimal price = gen().???; // How to generate this constrained BigDecimal?
        BigDecimal percentage = gen().???; // How to generate this constrained BigDecimal?
        return new Price(price, percentage);
    }
}

It seems as if the Generators API is more intended for internal use than for custom generators, e.g. the configure method expects the annotation type @InRange, which is hard to create an instance of. While custom generators are supposed to rely mainly on reflection. (Note that putting the fields on the Generator directly is not possible, because of inherited fields.)

Stim
  • 1,455
  • 14
  • 28

0 Answers0