junit-quickcheck: как писать генераторы идиоматическим способом
При написании генератора для junit-quickcheck легко использовать Ctor
или же Fields
методы отражения предоставляются. Но применение отражения непосредственно к моим бизнес-моделям не позволяет мне ограничивать сгенерированные данные (если я не чередую свои бизнес-модели с аннотациями quickcheck).
Например:
class Price {
public final BigDecimal price;
public final BigDecimal discountPercentage;
// With a constructor
}
Поле цены может быть любым (разумным) BigDecimal (скажем, до 1000), но скидка должна быть от 0 до 100.
Как написать генератор идиоматическим способом?
Мой текущий подход заключается в создании класса, который определяет модель для генерации:
class PriceFields {
public @InRange(max="1000") BigDecimal price;
public @InRange(max="100") BigDecimal discountPercentage;
public Price toPrice(){
return new Price(price, discountPercentage);
}
}
И генератор, как это:
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();
}
}
Но я хотел бы иметь возможность написать что-то вроде этого (без класса PriceFields):
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);
}
}
Кажется, как будто Generators
API больше предназначен для внутреннего использования, чем для пользовательских генераторов, например, метод configure ожидает тип аннотации @InRange
, который трудно создать экземпляр. В то время как нестандартные генераторы должны полагаться в основном на рефлексию. (Обратите внимание, что непосредственное размещение полей в Генераторе невозможно из-за унаследованных полей.)