how to represent nullable values with bogus?
Asked Answered
E

2

9

There is a beautiful library that generates random/pseudo-random values for a DTO.

    var fruit = new[] { "apple", "banana", "orange", "strawberry", "kiwi" };

var orderIds = 0;
var testOrders = new Faker<Order>()
    //Ensure all properties have rules. By default, StrictMode is false
    //Set a global policy by using Faker.DefaultStrictMode
    .StrictMode(true)
    //OrderId is deterministic
    .RuleFor(o => o.OrderId, f => orderIds++)
    //Pick some fruit from a basket
    .RuleFor(o => o.Item, f => f.PickRandom(fruit))
    //A random quantity from 1 to 10
    .RuleFor(o => o.Quantity, f => f.Random.Number(1, 10));

To create a rule for an int is simple:

            .RuleForType(typeof(int), f => f.Random.Number(10, 1000))

How do we create rules for nullable primitive types?

For example if our model has nullable ints or nullable deimcals:

public class ObjectWithNullables
{

  public int? mynumber{get;set;}
  public decimal? mydec {get;set;}
}

We cannot construct like so:

.RuleForType(typeof(int?), f => f.Random.Number(10, 1000))

How do we represent nullables?

Elk answered 27/12, 2017 at 18:49 Comment(1)
What happens when you try your example RuleForType? Have you read the documentation?Notepaper
N
7

A quick perusal seems to indicate you only need to use RuleForType when you are attempting to provide a single rule for all field/properties of a given type.

I think your issue with RuleForType is you did not pass in a lambda that returned the correct type. The type as the first parameter must match the return type of the lambda. Use

.RuleForType(typeof(int?), f => (int?)f.Random.Number(10, 1000))

If you need some possibility of null values, choose a percentage and return null occasionally:

.RuleForType(typeof(int?), f => (f.Random.Number(1,10) == 1 ? (int?)null : f.Random.Number(10, 1000)))
Notepaper answered 27/12, 2017 at 19:15 Comment(2)
But this will never return 'null' value for given property (assuming it will even work), so such implementation is not very good, since null is valid value.Burkitt
Now you are asking a different question altogether. Answer modified.Notepaper
P
19

Bogus has a .OrNull()/.OrDefault() extension methods in the Bogus.Extensions namespace.

To generate values that are randomly null try the following:

using Bogus.Extensions;

public class ObjectWithNullables
{
   public int? mynumber{get;set;}
   public decimal? mydec {get;set;}
}

var faker = new Faker<ObjectWithNullables>()
            // Generate null 20% of the time.
            .RuleFor(x=> x.mynumber, f=>f.Random.Number(10,1000).OrNull(f, .2f))
            // Generate null 70% of the time.
            .RuleFor(x=>x.mydec, f => f.Random.Decimal(8, 10).OrNull(f, .7f));

faker.Generate(10).Dump();

sample output

Hope that helps!

Thanks,
Brian

Poster answered 3/10, 2018 at 23:40 Comment(0)
N
7

A quick perusal seems to indicate you only need to use RuleForType when you are attempting to provide a single rule for all field/properties of a given type.

I think your issue with RuleForType is you did not pass in a lambda that returned the correct type. The type as the first parameter must match the return type of the lambda. Use

.RuleForType(typeof(int?), f => (int?)f.Random.Number(10, 1000))

If you need some possibility of null values, choose a percentage and return null occasionally:

.RuleForType(typeof(int?), f => (f.Random.Number(1,10) == 1 ? (int?)null : f.Random.Number(10, 1000)))
Notepaper answered 27/12, 2017 at 19:15 Comment(2)
But this will never return 'null' value for given property (assuming it will even work), so such implementation is not very good, since null is valid value.Burkitt
Now you are asking a different question altogether. Answer modified.Notepaper

© 2022 - 2024 — McMap. All rights reserved.