nickdodd79 / AutoBogus

A C# library complementing the Bogus generator by adding auto creation and population capabilities.
MIT License
423 stars 49 forks source link

Prevent generating negative numbers with auto bogus #99

Open mehdihadeli opened 1 year ago

mehdihadeli commented 1 year ago

Hi, I want to prevent to generating negative numbers for all of my number fields, Is there any way to set this globally?

dannyfelix commented 1 year ago

Hey @mehdihadeli -

You use the rule RuleForType<TType>(Type type, Func setterForType) to define rules for specific types across an entire object.

You can then use the methods available in Faker.Random in the setterForType function to define the range for the numbers generated. You will need to set this for each numeric type you need, e.g. int, uint, double, decimal, float, etc.

(N.B. nullable numeric types int?, decimal?, etc will need their own rule and will need an additional method call of OrNull<T>(this T value, Faker f, float nullWeight = 0.5f) or OrDefault<T>(this T value, Faker f, float defaultWeight = 0.5f, T defaultValue = default)

For example:

var pocoFaker = new AutoFaker<YourObject>()
    .RuleForType(typeof(int), faker => faker.Random.Int(min: 0, max: int.MaxValue))
    .RuleForType(typeof(decimal), faker => faker.Random.Decimal(min: 0M, max: decimal.MaxValue))
    .RuleForType(typeof(int?), faker => faker.Random.Int(min: 0, int.MaxValue).OrNull(faker, nullWeight: 0))
    .Generate();

Hope this helps (if you haven't already managed to figure this out yourself) 🙂

mehdihadeli commented 1 year ago

@dannyfelix Hi, Thanks for your response. That is exactly what I want, I couldn't find this in the Bogus docs, Is there this in their docs? I think we could have this in a more golbal way, for example some functionality inner AutoFaker.Configure, instead of defining this in each AutoFaker or Faker instance.

dannyfelix commented 1 year ago

@mehdihadeli Glad to hear it.

Doesn't seem to be in any documentation, I figured out how to do it because I had the same issue and came across these Stack Overflow questions:

I did initially look into applying the logic in a global configuration but couldn't figure it out at the time. I decided to take another look and figured out that, rather than use rules to ensure the generated values meet certain conditions, you can create custom generator overrides which will override the values generated.

Here's an example:

public class CustomIntGenerator : AutoGeneratorOverride
{
    public override bool CanOverride(AutoGenerateContext context)
    {
        return context.GenerateType == typeof(int);
    }

    public override void Generate(AutoGenerateOverrideContext context)
    {
        if (context.Instance is not int) return;

        context.Instance = context.Faker.Random.Int(0);
    }
}

You can then apply this in the global configuration:

AutoFaker.Configure(builder => 
{
    builder.WithOverride(new CustomIntGenerator());
});

You can then apply the same logic to create overrides for other numeric types.